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
Kirill Smelkov
linux
Commits
294cb923
Commit
294cb923
authored
Feb 18, 2003
by
Jon Grimm
Browse files
Options
Browse Files
Download
Plain Diff
Merge
http://linux-lksctp.bkbits.net/lksctp-2.5
into touki.austin.ibm.com:/home/jgrimm/bk/lksctp-2.5.work
parents
9967b51f
28131078
Changes
9
Show whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
272 additions
and
119 deletions
+272
-119
include/net/sctp/command.h
include/net/sctp/command.h
+2
-3
include/net/sctp/tsnmap.h
include/net/sctp/tsnmap.h
+18
-13
include/net/sctp/ulpqueue.h
include/net/sctp/ulpqueue.h
+3
-0
net/sctp/associola.c
net/sctp/associola.c
+2
-2
net/sctp/sm_sideeffect.c
net/sctp/sm_sideeffect.c
+57
-75
net/sctp/sm_statefuns.c
net/sctp/sm_statefuns.c
+28
-20
net/sctp/socket.c
net/sctp/socket.c
+49
-0
net/sctp/tsnmap.c
net/sctp/tsnmap.c
+20
-0
net/sctp/ulpqueue.c
net/sctp/ulpqueue.c
+93
-6
No files found.
include/net/sctp/command.h
View file @
294cb923
...
@@ -68,7 +68,6 @@ typedef enum {
...
@@ -68,7 +68,6 @@ typedef enum {
SCTP_CMD_INIT_RESTART
,
/* High level, do init timer work. */
SCTP_CMD_INIT_RESTART
,
/* High level, do init timer work. */
SCTP_CMD_INIT_FAILED
,
/* High level, do init failure work. */
SCTP_CMD_INIT_FAILED
,
/* High level, do init failure work. */
SCTP_CMD_REPORT_DUP
,
/* Report a duplicate TSN. */
SCTP_CMD_REPORT_DUP
,
/* Report a duplicate TSN. */
SCTP_CMD_REPORT_BIGGAP
,
/* Narc on a TSN (it was too high). */
SCTP_CMD_STRIKE
,
/* Mark a strike against a transport. */
SCTP_CMD_STRIKE
,
/* Mark a strike against a transport. */
SCTP_CMD_TRANSMIT
,
/* Transmit the outqueue. */
SCTP_CMD_TRANSMIT
,
/* Transmit the outqueue. */
SCTP_CMD_HB_TIMERS_START
,
/* Start the heartbeat timers. */
SCTP_CMD_HB_TIMERS_START
,
/* Start the heartbeat timers. */
...
@@ -86,8 +85,8 @@ typedef enum {
...
@@ -86,8 +85,8 @@ typedef enum {
SCTP_CMD_PURGE_OUTQUEUE
,
/* Purge all data waiting to be sent. */
SCTP_CMD_PURGE_OUTQUEUE
,
/* Purge all data waiting to be sent. */
SCTP_CMD_SETUP_T2
,
/* Hi-level, setup T2-shutdown parms. */
SCTP_CMD_SETUP_T2
,
/* Hi-level, setup T2-shutdown parms. */
SCTP_CMD_RTO_PENDING
,
/* Set transport's rto_pending. */
SCTP_CMD_RTO_PENDING
,
/* Set transport's rto_pending. */
SCTP_CMD_
CHUNK_PD
,
/* Partial data delivery considerations. */
SCTP_CMD_
PART_DELIVER
,
/* Partial data delivery considerations. */
SCTP_CMD_RENEGE
,
/* Renege data on an association. */
SCTP_CMD_LAST
SCTP_CMD_LAST
}
sctp_verb_t
;
}
sctp_verb_t
;
...
...
include/net/sctp/tsnmap.h
View file @
294cb923
...
@@ -12,7 +12,7 @@
...
@@ -12,7 +12,7 @@
* the Free Software Foundation; either version 2, or (at your option)
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
* any later version.
*
*
*
the SCTP reference implementation
is distributed in the hope that it
*
The SCTP reference implementation
is distributed in the hope that it
* will be useful, but WITHOUT ANY WARRANTY; without even the implied
* will be useful, but WITHOUT ANY WARRANTY; without even the implied
* ************************
* ************************
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
...
@@ -23,9 +23,14 @@
...
@@ -23,9 +23,14 @@
* the Free Software Foundation, 59 Temple Place - Suite 330,
* the Free Software Foundation, 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
* Boston, MA 02111-1307, USA.
*
*
* Please send any bug reports or fixes you make to one of the
* Please send any bug reports or fixes you make to the
* following email addresses:
* email address(es):
* lksctp developers <lksctp-developers@lists.sourceforge.net>
*
*
* Or submit a bug report through the following website:
* http://www.sf.net/projects/lksctp
*
* Written or modified by:
* Jon Grimm <jgrimm@us.ibm.com>
* Jon Grimm <jgrimm@us.ibm.com>
* La Monte H.P. Yarroll <piggy@acm.org>
* La Monte H.P. Yarroll <piggy@acm.org>
* Karl Knutson <karl@athena.chicago.il.us>
* Karl Knutson <karl@athena.chicago.il.us>
...
@@ -153,15 +158,18 @@ static inline __u32 *sctp_tsnmap_get_dups(struct sctp_tsnmap *map)
...
@@ -153,15 +158,18 @@ static inline __u32 *sctp_tsnmap_get_dups(struct sctp_tsnmap *map)
return
map
->
dup_tsns
;
return
map
->
dup_tsns
;
}
}
/* Mark a duplicate TSN. Note:
we limit how many we are willing to
/* Mark a duplicate TSN. Note:
limit the storage of duplicate TSN
*
store and consequently report
.
*
information
.
*/
*/
static
inline
void
sctp_tsnmap_mark_dup
(
struct
sctp_tsnmap
*
map
,
__u32
tsn
)
static
inline
void
sctp_tsnmap_mark_dup
(
struct
sctp_tsnmap
*
map
,
__u32
tsn
)
{
{
if
(
map
->
num_dup_tsns
<
SCTP_MAX_DUP_TSNS
)
if
(
map
->
num_dup_tsns
<
SCTP_MAX_DUP_TSNS
)
map
->
dup_tsns
[
map
->
num_dup_tsns
++
]
=
tsn
;
map
->
dup_tsns
[
map
->
num_dup_tsns
++
]
=
htonl
(
tsn
)
;
}
}
/* Renege a TSN that was seen. */
void
sctp_tsnmap_renege
(
struct
sctp_tsnmap
*
,
__u32
tsn
);
/* Is there a gap in the TSN map? */
/* Is there a gap in the TSN map? */
int
sctp_tsnmap_has_gap
(
const
struct
sctp_tsnmap
*
);
int
sctp_tsnmap_has_gap
(
const
struct
sctp_tsnmap
*
);
...
@@ -176,6 +184,3 @@ int sctp_tsnmap_next_gap_ack(const struct sctp_tsnmap *,
...
@@ -176,6 +184,3 @@ int sctp_tsnmap_next_gap_ack(const struct sctp_tsnmap *,
struct
sctp_tsnmap_iter
*
,
__u16
*
start
,
__u16
*
end
);
struct
sctp_tsnmap_iter
*
,
__u16
*
start
,
__u16
*
end
);
#endif
/* __sctp_tsnmap_h__ */
#endif
/* __sctp_tsnmap_h__ */
include/net/sctp/ulpqueue.h
View file @
294cb923
...
@@ -66,6 +66,9 @@ int sctp_ulpq_tail_data(struct sctp_ulpq *, struct sctp_chunk *, int);
...
@@ -66,6 +66,9 @@ int sctp_ulpq_tail_data(struct sctp_ulpq *, struct sctp_chunk *, int);
/* Add a new event for propogation to the ULP. */
/* Add a new event for propogation to the ULP. */
int
sctp_ulpq_tail_event
(
struct
sctp_ulpq
*
,
struct
sctp_ulpevent
*
ev
);
int
sctp_ulpq_tail_event
(
struct
sctp_ulpq
*
,
struct
sctp_ulpevent
*
ev
);
/* Renege previously received chunks. */
void
sctp_ulpq_renege
(
struct
sctp_ulpq
*
,
struct
sctp_chunk
*
,
int
);
/* Perform partial delivery. */
/* Perform partial delivery. */
void
sctp_ulpq_partial_delivery
(
struct
sctp_ulpq
*
,
struct
sctp_chunk
*
,
int
);
void
sctp_ulpq_partial_delivery
(
struct
sctp_ulpq
*
,
struct
sctp_chunk
*
,
int
);
...
...
net/sctp/associola.c
View file @
294cb923
...
@@ -1014,8 +1014,8 @@ void sctp_assoc_rwnd_increase(sctp_association_t *asoc, int len)
...
@@ -1014,8 +1014,8 @@ void sctp_assoc_rwnd_increase(sctp_association_t *asoc, int len)
((
asoc
->
rwnd
-
asoc
->
a_rwnd
)
>=
((
asoc
->
rwnd
-
asoc
->
a_rwnd
)
>=
min_t
(
__u32
,
(
asoc
->
base
.
sk
->
rcvbuf
>>
1
),
asoc
->
pmtu
)))
{
min_t
(
__u32
,
(
asoc
->
base
.
sk
->
rcvbuf
>>
1
),
asoc
->
pmtu
)))
{
SCTP_DEBUG_PRINTK
(
"%s: Sending window update SACK- asoc: %p "
SCTP_DEBUG_PRINTK
(
"%s: Sending window update SACK- asoc: %p "
"rwnd: %u a_rwnd: %u
\n
"
,
"rwnd: %u a_rwnd: %u
\n
"
,
__FUNCTION__
,
__FUNCTION__
,
asoc
,
asoc
->
rwnd
,
asoc
->
a_rwnd
);
asoc
,
asoc
->
rwnd
,
asoc
->
a_rwnd
);
sack
=
sctp_make_sack
(
asoc
);
sack
=
sctp_make_sack
(
asoc
);
if
(
!
sack
)
if
(
!
sack
)
return
;
return
;
...
...
net/sctp/sm_sideeffect.c
View file @
294cb923
...
@@ -253,7 +253,7 @@ int sctp_cmd_interpreter(sctp_event_t event_type, sctp_subtype_t subtype,
...
@@ -253,7 +253,7 @@ int sctp_cmd_interpreter(sctp_event_t event_type, sctp_subtype_t subtype,
{
{
int
error
=
0
;
int
error
=
0
;
int
force
;
int
force
;
sctp_cmd_t
*
c
omman
d
;
sctp_cmd_t
*
c
m
d
;
sctp_chunk_t
*
new_obj
;
sctp_chunk_t
*
new_obj
;
sctp_chunk_t
*
chunk
=
NULL
;
sctp_chunk_t
*
chunk
=
NULL
;
sctp_packet_t
*
packet
;
sctp_packet_t
*
packet
;
...
@@ -273,22 +273,22 @@ int sctp_cmd_interpreter(sctp_event_t event_type, sctp_subtype_t subtype,
...
@@ -273,22 +273,22 @@ int sctp_cmd_interpreter(sctp_event_t event_type, sctp_subtype_t subtype,
* cmd->handle(x, y, z)
* cmd->handle(x, y, z)
* --jgrimm
* --jgrimm
*/
*/
while
(
NULL
!=
(
c
omman
d
=
sctp_next_cmd
(
commands
)))
{
while
(
NULL
!=
(
c
m
d
=
sctp_next_cmd
(
commands
)))
{
switch
(
c
omman
d
->
verb
)
{
switch
(
c
m
d
->
verb
)
{
case
SCTP_CMD_NOP
:
case
SCTP_CMD_NOP
:
/* Do nothing. */
/* Do nothing. */
break
;
break
;
case
SCTP_CMD_NEW_ASOC
:
case
SCTP_CMD_NEW_ASOC
:
/* Register a new association. */
/* Register a new association. */
asoc
=
c
omman
d
->
obj
.
ptr
;
asoc
=
c
m
d
->
obj
.
ptr
;
/* Register with the endpoint. */
/* Register with the endpoint. */
sctp_endpoint_add_asoc
(
ep
,
asoc
);
sctp_endpoint_add_asoc
(
ep
,
asoc
);
sctp_hash_established
(
asoc
);
sctp_hash_established
(
asoc
);
break
;
break
;
case
SCTP_CMD_UPDATE_ASSOC
:
case
SCTP_CMD_UPDATE_ASSOC
:
sctp_assoc_update
(
asoc
,
c
omman
d
->
obj
.
ptr
);
sctp_assoc_update
(
asoc
,
c
m
d
->
obj
.
ptr
);
break
;
break
;
case
SCTP_CMD_PURGE_OUTQUEUE
:
case
SCTP_CMD_PURGE_OUTQUEUE
:
...
@@ -304,13 +304,12 @@ int sctp_cmd_interpreter(sctp_event_t event_type, sctp_subtype_t subtype,
...
@@ -304,13 +304,12 @@ int sctp_cmd_interpreter(sctp_event_t event_type, sctp_subtype_t subtype,
case
SCTP_CMD_NEW_STATE
:
case
SCTP_CMD_NEW_STATE
:
/* Enter a new state. */
/* Enter a new state. */
sctp_cmd_new_state
(
commands
,
asoc
,
c
omman
d
->
obj
.
state
);
sctp_cmd_new_state
(
commands
,
asoc
,
c
m
d
->
obj
.
state
);
break
;
break
;
case
SCTP_CMD_REPORT_TSN
:
case
SCTP_CMD_REPORT_TSN
:
/* Record the arrival of a TSN. */
/* Record the arrival of a TSN. */
sctp_tsnmap_mark
(
&
asoc
->
peer
.
tsn_map
,
sctp_tsnmap_mark
(
&
asoc
->
peer
.
tsn_map
,
cmd
->
obj
.
u32
);
command
->
obj
.
u32
);
break
;
break
;
case
SCTP_CMD_GEN_SACK
:
case
SCTP_CMD_GEN_SACK
:
...
@@ -319,14 +318,14 @@ int sctp_cmd_interpreter(sctp_event_t event_type, sctp_subtype_t subtype,
...
@@ -319,14 +318,14 @@ int sctp_cmd_interpreter(sctp_event_t event_type, sctp_subtype_t subtype,
* the packet and MAYBE generate a SACK, or
* the packet and MAYBE generate a SACK, or
* force a SACK out.
* force a SACK out.
*/
*/
force
=
c
omman
d
->
obj
.
i32
;
force
=
c
m
d
->
obj
.
i32
;
error
=
sctp_gen_sack
(
asoc
,
force
,
commands
);
error
=
sctp_gen_sack
(
asoc
,
force
,
commands
);
break
;
break
;
case
SCTP_CMD_PROCESS_SACK
:
case
SCTP_CMD_PROCESS_SACK
:
/* Process an inbound SACK. */
/* Process an inbound SACK. */
error
=
sctp_cmd_process_sack
(
commands
,
asoc
,
error
=
sctp_cmd_process_sack
(
commands
,
asoc
,
c
omman
d
->
obj
.
ptr
);
c
m
d
->
obj
.
ptr
);
break
;
break
;
case
SCTP_CMD_GEN_INIT_ACK
:
case
SCTP_CMD_GEN_INIT_ACK
:
...
@@ -347,16 +346,15 @@ int sctp_cmd_interpreter(sctp_event_t event_type, sctp_subtype_t subtype,
...
@@ -347,16 +346,15 @@ int sctp_cmd_interpreter(sctp_event_t event_type, sctp_subtype_t subtype,
* layer which will bail.
* layer which will bail.
*/
*/
error
=
sctp_cmd_process_init
(
commands
,
asoc
,
chunk
,
error
=
sctp_cmd_process_init
(
commands
,
asoc
,
chunk
,
command
->
obj
.
ptr
,
cmd
->
obj
.
ptr
,
priority
);
priority
);
break
;
break
;
case
SCTP_CMD_GEN_COOKIE_ECHO
:
case
SCTP_CMD_GEN_COOKIE_ECHO
:
/* Generate a COOKIE ECHO chunk. */
/* Generate a COOKIE ECHO chunk. */
new_obj
=
sctp_make_cookie_echo
(
asoc
,
chunk
);
new_obj
=
sctp_make_cookie_echo
(
asoc
,
chunk
);
if
(
!
new_obj
)
{
if
(
!
new_obj
)
{
if
(
c
omman
d
->
obj
.
ptr
)
if
(
c
m
d
->
obj
.
ptr
)
sctp_free_chunk
(
c
omman
d
->
obj
.
ptr
);
sctp_free_chunk
(
c
m
d
->
obj
.
ptr
);
goto
nomem
;
goto
nomem
;
}
}
sctp_add_cmd_sf
(
commands
,
SCTP_CMD_REPLY
,
sctp_add_cmd_sf
(
commands
,
SCTP_CMD_REPLY
,
...
@@ -365,9 +363,9 @@ int sctp_cmd_interpreter(sctp_event_t event_type, sctp_subtype_t subtype,
...
@@ -365,9 +363,9 @@ int sctp_cmd_interpreter(sctp_event_t event_type, sctp_subtype_t subtype,
/* If there is an ERROR chunk to be sent along with
/* If there is an ERROR chunk to be sent along with
* the COOKIE_ECHO, send it, too.
* the COOKIE_ECHO, send it, too.
*/
*/
if
(
c
omman
d
->
obj
.
ptr
)
if
(
c
m
d
->
obj
.
ptr
)
sctp_add_cmd_sf
(
commands
,
SCTP_CMD_REPLY
,
sctp_add_cmd_sf
(
commands
,
SCTP_CMD_REPLY
,
SCTP_CHUNK
(
c
omman
d
->
obj
.
ptr
));
SCTP_CHUNK
(
c
m
d
->
obj
.
ptr
));
break
;
break
;
case
SCTP_CMD_GEN_SHUTDOWN
:
case
SCTP_CMD_GEN_SHUTDOWN
:
...
@@ -387,43 +385,36 @@ int sctp_cmd_interpreter(sctp_event_t event_type, sctp_subtype_t subtype,
...
@@ -387,43 +385,36 @@ int sctp_cmd_interpreter(sctp_event_t event_type, sctp_subtype_t subtype,
case
SCTP_CMD_CHUNK_ULP
:
case
SCTP_CMD_CHUNK_ULP
:
/* Send a chunk to the sockets layer. */
/* Send a chunk to the sockets layer. */
SCTP_DEBUG_PRINTK
(
"sm_sideff: %s %p, %s %p.
\n
"
,
SCTP_DEBUG_PRINTK
(
"sm_sideff: %s %p, %s %p.
\n
"
,
"chunk_up:"
,
"chunk_up:"
,
cmd
->
obj
.
ptr
,
command
->
obj
.
ptr
,
"ulpq:"
,
&
asoc
->
ulpq
);
"ulpq:"
,
sctp_ulpq_tail_data
(
&
asoc
->
ulpq
,
cmd
->
obj
.
ptr
,
&
asoc
->
ulpq
);
sctp_ulpq_tail_data
(
&
asoc
->
ulpq
,
command
->
obj
.
ptr
,
GFP_ATOMIC
);
GFP_ATOMIC
);
break
;
break
;
case
SCTP_CMD_EVENT_ULP
:
case
SCTP_CMD_EVENT_ULP
:
/* Send a notification to the sockets layer. */
/* Send a notification to the sockets layer. */
SCTP_DEBUG_PRINTK
(
"sm_sideff: %s %p, %s %p.
\n
"
,
SCTP_DEBUG_PRINTK
(
"sm_sideff: %s %p, %s %p.
\n
"
,
"event_up:"
,
"event_up:"
,
cmd
->
obj
.
ptr
,
command
->
obj
.
ptr
,
"ulpq:"
,
&
asoc
->
ulpq
);
"ulpq:"
,
sctp_ulpq_tail_event
(
&
asoc
->
ulpq
,
cmd
->
obj
.
ptr
);
&
asoc
->
ulpq
);
sctp_ulpq_tail_event
(
&
asoc
->
ulpq
,
command
->
obj
.
ptr
);
break
;
break
;
case
SCTP_CMD_REPLY
:
case
SCTP_CMD_REPLY
:
/* Send a chunk to our peer. */
/* Send a chunk to our peer. */
error
=
sctp_outq_tail
(
&
asoc
->
outqueue
,
error
=
sctp_outq_tail
(
&
asoc
->
outqueue
,
c
omman
d
->
obj
.
ptr
);
c
m
d
->
obj
.
ptr
);
break
;
break
;
case
SCTP_CMD_SEND_PKT
:
case
SCTP_CMD_SEND_PKT
:
/* Send a full packet to our peer. */
/* Send a full packet to our peer. */
packet
=
c
omman
d
->
obj
.
ptr
;
packet
=
c
m
d
->
obj
.
ptr
;
sctp_packet_transmit
(
packet
);
sctp_packet_transmit
(
packet
);
sctp_ootb_pkt_free
(
packet
);
sctp_ootb_pkt_free
(
packet
);
break
;
break
;
case
SCTP_CMD_RETRAN
:
case
SCTP_CMD_RETRAN
:
/* Mark a transport for retransmission. */
/* Mark a transport for retransmission. */
sctp_retransmit
(
&
asoc
->
outqueue
,
sctp_retransmit
(
&
asoc
->
outqueue
,
cmd
->
obj
.
transport
,
command
->
obj
.
transport
,
SCTP_RETRANSMIT_T3_RTX
);
SCTP_RETRANSMIT_T3_RTX
);
break
;
break
;
...
@@ -434,32 +425,30 @@ int sctp_cmd_interpreter(sctp_event_t event_type, sctp_subtype_t subtype,
...
@@ -434,32 +425,30 @@ int sctp_cmd_interpreter(sctp_event_t event_type, sctp_subtype_t subtype,
case
SCTP_CMD_ECN_CE
:
case
SCTP_CMD_ECN_CE
:
/* Do delayed CE processing. */
/* Do delayed CE processing. */
sctp_do_ecn_ce_work
(
asoc
,
c
omman
d
->
obj
.
u32
);
sctp_do_ecn_ce_work
(
asoc
,
c
m
d
->
obj
.
u32
);
break
;
break
;
case
SCTP_CMD_ECN_ECNE
:
case
SCTP_CMD_ECN_ECNE
:
/* Do delayed ECNE processing. */
/* Do delayed ECNE processing. */
new_obj
=
sctp_do_ecn_ecne_work
(
asoc
,
new_obj
=
sctp_do_ecn_ecne_work
(
asoc
,
cmd
->
obj
.
u32
,
command
->
obj
.
u32
,
chunk
);
chunk
);
if
(
new_obj
)
{
if
(
new_obj
)
sctp_add_cmd_sf
(
commands
,
SCTP_CMD_REPLY
,
sctp_add_cmd_sf
(
commands
,
SCTP_CMD_REPLY
,
SCTP_CHUNK
(
new_obj
));
SCTP_CHUNK
(
new_obj
));
}
break
;
break
;
case
SCTP_CMD_ECN_CWR
:
case
SCTP_CMD_ECN_CWR
:
/* Do delayed CWR processing. */
/* Do delayed CWR processing. */
sctp_do_ecn_cwr_work
(
asoc
,
c
omman
d
->
obj
.
u32
);
sctp_do_ecn_cwr_work
(
asoc
,
c
m
d
->
obj
.
u32
);
break
;
break
;
case
SCTP_CMD_SETUP_T2
:
case
SCTP_CMD_SETUP_T2
:
sctp_cmd_setup_t2
(
commands
,
asoc
,
c
omman
d
->
obj
.
ptr
);
sctp_cmd_setup_t2
(
commands
,
asoc
,
c
m
d
->
obj
.
ptr
);
break
;
break
;
case
SCTP_CMD_TIMER_START
:
case
SCTP_CMD_TIMER_START
:
timer
=
&
asoc
->
timers
[
c
omman
d
->
obj
.
to
];
timer
=
&
asoc
->
timers
[
c
m
d
->
obj
.
to
];
timeout
=
asoc
->
timeouts
[
c
omman
d
->
obj
.
to
];
timeout
=
asoc
->
timeouts
[
c
m
d
->
obj
.
to
];
if
(
!
timeout
)
if
(
!
timeout
)
BUG
();
BUG
();
...
@@ -469,29 +458,28 @@ int sctp_cmd_interpreter(sctp_event_t event_type, sctp_subtype_t subtype,
...
@@ -469,29 +458,28 @@ int sctp_cmd_interpreter(sctp_event_t event_type, sctp_subtype_t subtype,
break
;
break
;
case
SCTP_CMD_TIMER_RESTART
:
case
SCTP_CMD_TIMER_RESTART
:
timer
=
&
asoc
->
timers
[
c
omman
d
->
obj
.
to
];
timer
=
&
asoc
->
timers
[
c
m
d
->
obj
.
to
];
timeout
=
asoc
->
timeouts
[
c
omman
d
->
obj
.
to
];
timeout
=
asoc
->
timeouts
[
c
m
d
->
obj
.
to
];
if
(
!
mod_timer
(
timer
,
jiffies
+
timeout
))
if
(
!
mod_timer
(
timer
,
jiffies
+
timeout
))
sctp_association_hold
(
asoc
);
sctp_association_hold
(
asoc
);
break
;
break
;
case
SCTP_CMD_TIMER_STOP
:
case
SCTP_CMD_TIMER_STOP
:
timer
=
&
asoc
->
timers
[
c
omman
d
->
obj
.
to
];
timer
=
&
asoc
->
timers
[
c
m
d
->
obj
.
to
];
if
(
timer_pending
(
timer
)
&&
del_timer
(
timer
))
if
(
timer_pending
(
timer
)
&&
del_timer
(
timer
))
sctp_association_put
(
asoc
);
sctp_association_put
(
asoc
);
break
;
break
;
case
SCTP_CMD_INIT_RESTART
:
case
SCTP_CMD_INIT_RESTART
:
/* Do the needed accounting and updates
/* Do the needed accounting and updates
* associated with restarting an initialization
* associated with restarting an initialization
* timer.
* timer.
*/
*/
asoc
->
counters
[
SCTP_COUNTER_INIT_ERROR
]
++
;
asoc
->
counters
[
SCTP_COUNTER_INIT_ERROR
]
++
;
asoc
->
timeouts
[
c
omman
d
->
obj
.
to
]
*=
2
;
asoc
->
timeouts
[
c
m
d
->
obj
.
to
]
*=
2
;
if
(
asoc
->
timeouts
[
c
omman
d
->
obj
.
to
]
>
if
(
asoc
->
timeouts
[
c
m
d
->
obj
.
to
]
>
asoc
->
max_init_timeo
)
{
asoc
->
max_init_timeo
)
{
asoc
->
timeouts
[
c
omman
d
->
obj
.
to
]
=
asoc
->
timeouts
[
c
m
d
->
obj
.
to
]
=
asoc
->
max_init_timeo
;
asoc
->
max_init_timeo
;
}
}
...
@@ -506,7 +494,7 @@ int sctp_cmd_interpreter(sctp_event_t event_type, sctp_subtype_t subtype,
...
@@ -506,7 +494,7 @@ int sctp_cmd_interpreter(sctp_event_t event_type, sctp_subtype_t subtype,
sctp_add_cmd_sf
(
commands
,
sctp_add_cmd_sf
(
commands
,
SCTP_CMD_TIMER_RESTART
,
SCTP_CMD_TIMER_RESTART
,
SCTP_TO
(
c
omman
d
->
obj
.
to
));
SCTP_TO
(
c
m
d
->
obj
.
to
));
break
;
break
;
case
SCTP_CMD_INIT_FAILED
:
case
SCTP_CMD_INIT_FAILED
:
...
@@ -519,23 +507,16 @@ int sctp_cmd_interpreter(sctp_event_t event_type, sctp_subtype_t subtype,
...
@@ -519,23 +507,16 @@ int sctp_cmd_interpreter(sctp_event_t event_type, sctp_subtype_t subtype,
break
;
break
;
case
SCTP_CMD_COUNTER_INC
:
case
SCTP_CMD_COUNTER_INC
:
asoc
->
counters
[
c
omman
d
->
obj
.
counter
]
++
;
asoc
->
counters
[
c
m
d
->
obj
.
counter
]
++
;
break
;
break
;
case
SCTP_CMD_COUNTER_RESET
:
case
SCTP_CMD_COUNTER_RESET
:
asoc
->
counters
[
c
omman
d
->
obj
.
counter
]
=
0
;
asoc
->
counters
[
c
m
d
->
obj
.
counter
]
=
0
;
break
;
break
;
case
SCTP_CMD_REPORT_DUP
:
case
SCTP_CMD_REPORT_DUP
:
sctp_tsnmap_mark_dup
(
&
asoc
->
peer
.
tsn_map
,
sctp_tsnmap_mark_dup
(
&
asoc
->
peer
.
tsn_map
,
ntohl
(
command
->
obj
.
u32
));
cmd
->
obj
.
u32
);
break
;
case
SCTP_CMD_REPORT_BIGGAP
:
SCTP_DEBUG_PRINTK
(
"Big gap: %x to %x
\n
"
,
sctp_tsnmap_get_ctsn
(
&
asoc
->
peer
.
tsn_map
),
command
->
obj
.
u32
);
break
;
break
;
case
SCTP_CMD_REPORT_BAD_TAG
:
case
SCTP_CMD_REPORT_BAD_TAG
:
...
@@ -544,17 +525,16 @@ int sctp_cmd_interpreter(sctp_event_t event_type, sctp_subtype_t subtype,
...
@@ -544,17 +525,16 @@ int sctp_cmd_interpreter(sctp_event_t event_type, sctp_subtype_t subtype,
case
SCTP_CMD_STRIKE
:
case
SCTP_CMD_STRIKE
:
/* Mark one strike against a transport. */
/* Mark one strike against a transport. */
sctp_do_8_2_transport_strike
(
asoc
,
sctp_do_8_2_transport_strike
(
asoc
,
cmd
->
obj
.
transport
);
command
->
obj
.
transport
);
break
;
break
;
case
SCTP_CMD_TRANSPORT_RESET
:
case
SCTP_CMD_TRANSPORT_RESET
:
t
=
c
omman
d
->
obj
.
transport
;
t
=
c
m
d
->
obj
.
transport
;
sctp_cmd_transport_reset
(
commands
,
asoc
,
t
);
sctp_cmd_transport_reset
(
commands
,
asoc
,
t
);
break
;
break
;
case
SCTP_CMD_TRANSPORT_ON
:
case
SCTP_CMD_TRANSPORT_ON
:
t
=
c
omman
d
->
obj
.
transport
;
t
=
c
m
d
->
obj
.
transport
;
sctp_cmd_transport_on
(
commands
,
asoc
,
t
,
chunk
);
sctp_cmd_transport_on
(
commands
,
asoc
,
t
,
chunk
);
break
;
break
;
...
@@ -563,7 +543,7 @@ int sctp_cmd_interpreter(sctp_event_t event_type, sctp_subtype_t subtype,
...
@@ -563,7 +543,7 @@ int sctp_cmd_interpreter(sctp_event_t event_type, sctp_subtype_t subtype,
break
;
break
;
case
SCTP_CMD_HB_TIMER_UPDATE
:
case
SCTP_CMD_HB_TIMER_UPDATE
:
t
=
c
omman
d
->
obj
.
transport
;
t
=
c
m
d
->
obj
.
transport
;
sctp_cmd_hb_timer_update
(
commands
,
asoc
,
t
);
sctp_cmd_hb_timer_update
(
commands
,
asoc
,
t
);
break
;
break
;
...
@@ -572,17 +552,16 @@ int sctp_cmd_interpreter(sctp_event_t event_type, sctp_subtype_t subtype,
...
@@ -572,17 +552,16 @@ int sctp_cmd_interpreter(sctp_event_t event_type, sctp_subtype_t subtype,
break
;
break
;
case
SCTP_CMD_REPORT_ERROR
:
case
SCTP_CMD_REPORT_ERROR
:
error
=
c
omman
d
->
obj
.
error
;
error
=
c
m
d
->
obj
.
error
;
break
;
break
;
case
SCTP_CMD_PROCESS_CTSN
:
case
SCTP_CMD_PROCESS_CTSN
:
/* Dummy up a SACK for processing. */
/* Dummy up a SACK for processing. */
sackh
.
cum_tsn_ack
=
c
omman
d
->
obj
.
u32
;
sackh
.
cum_tsn_ack
=
c
m
d
->
obj
.
u32
;
sackh
.
a_rwnd
=
0
;
sackh
.
a_rwnd
=
0
;
sackh
.
num_gap_ack_blocks
=
0
;
sackh
.
num_gap_ack_blocks
=
0
;
sackh
.
num_dup_tsns
=
0
;
sackh
.
num_dup_tsns
=
0
;
sctp_add_cmd_sf
(
commands
,
sctp_add_cmd_sf
(
commands
,
SCTP_CMD_PROCESS_SACK
,
SCTP_CMD_PROCESS_SACK
,
SCTP_SACKH
(
&
sackh
));
SCTP_SACKH
(
&
sackh
));
break
;
break
;
...
@@ -592,20 +571,23 @@ int sctp_cmd_interpreter(sctp_event_t event_type, sctp_subtype_t subtype,
...
@@ -592,20 +571,23 @@ int sctp_cmd_interpreter(sctp_event_t event_type, sctp_subtype_t subtype,
break
;
break
;
case
SCTP_CMD_RTO_PENDING
:
case
SCTP_CMD_RTO_PENDING
:
t
=
c
omman
d
->
obj
.
transport
;
t
=
c
m
d
->
obj
.
transport
;
t
->
rto_pending
=
1
;
t
->
rto_pending
=
1
;
break
;
break
;
case
SCTP_CMD_CHUNK_PD
:
case
SCTP_CMD_PART_DELIVER
:
/* Send a chunk to the sockets layer. */
sctp_ulpq_partial_delivery
(
&
asoc
->
ulpq
,
cmd
->
obj
.
ptr
,
sctp_ulpq_partial_delivery
(
&
asoc
->
ulpq
,
GFP_ATOMIC
);
command
->
obj
.
ptr
,
break
;
case
SCTP_CMD_RENEGE
:
sctp_ulpq_renege
(
&
asoc
->
ulpq
,
cmd
->
obj
.
ptr
,
GFP_ATOMIC
);
GFP_ATOMIC
);
break
;
break
;
default:
default:
printk
(
KERN_WARNING
"Impossible command: %u, %p
\n
"
,
printk
(
KERN_WARNING
"Impossible command: %u, %p
\n
"
,
c
ommand
->
verb
,
comman
d
->
obj
.
ptr
);
c
md
->
verb
,
cm
d
->
obj
.
ptr
);
break
;
break
;
};
};
if
(
error
)
if
(
error
)
...
...
net/sctp/sm_statefuns.c
View file @
294cb923
...
@@ -682,7 +682,6 @@ sctp_disposition_t sctp_sf_do_5_1E_ca(const sctp_endpoint_t *ep,
...
@@ -682,7 +682,6 @@ sctp_disposition_t sctp_sf_do_5_1E_ca(const sctp_endpoint_t *ep,
sctp_add_cmd_sf
(
commands
,
SCTP_CMD_EVENT_ULP
,
SCTP_ULPEVENT
(
ev
));
sctp_add_cmd_sf
(
commands
,
SCTP_CMD_EVENT_ULP
,
SCTP_ULPEVENT
(
ev
));
return
SCTP_DISPOSITION_CONSUME
;
return
SCTP_DISPOSITION_CONSUME
;
nomem:
nomem:
return
SCTP_DISPOSITION_NOMEM
;
return
SCTP_DISPOSITION_NOMEM
;
}
}
...
@@ -2274,7 +2273,6 @@ sctp_disposition_t sctp_sf_eat_data_6_2(const sctp_endpoint_t *ep,
...
@@ -2274,7 +2273,6 @@ sctp_disposition_t sctp_sf_eat_data_6_2(const sctp_endpoint_t *ep,
* that the value in the Verification Tag field of the
* that the value in the Verification Tag field of the
* received SCTP packet matches its own Tag.
* received SCTP packet matches its own Tag.
*/
*/
if
(
ntohl
(
chunk
->
sctp_hdr
->
vtag
)
!=
asoc
->
c
.
my_vtag
)
{
if
(
ntohl
(
chunk
->
sctp_hdr
->
vtag
)
!=
asoc
->
c
.
my_vtag
)
{
sctp_add_cmd_sf
(
commands
,
SCTP_CMD_REPORT_BAD_TAG
,
sctp_add_cmd_sf
(
commands
,
SCTP_CMD_REPORT_BAD_TAG
,
SCTP_NULL
());
SCTP_NULL
());
...
@@ -2339,18 +2337,26 @@ sctp_disposition_t sctp_sf_eat_data_6_2(const sctp_endpoint_t *ep,
...
@@ -2339,18 +2337,26 @@ sctp_disposition_t sctp_sf_eat_data_6_2(const sctp_endpoint_t *ep,
/* Even if we don't accept this chunk there is
/* Even if we don't accept this chunk there is
* memory pressure.
* memory pressure.
*/
*/
sctp_add_cmd_sf
(
commands
,
SCTP_CMD_
CHUNK_PD
,
SCTP_NULL
());
sctp_add_cmd_sf
(
commands
,
SCTP_CMD_
PART_DELIVER
,
SCTP_NULL
());
}
}
/* Spill over rwnd a little bit. Note: While allowed, this spill over
* seems a bit troublesome in that frag_point varies based on
* PMTU. In cases, such as loopback, this might be a rather
* large spill over.
*/
if
(
asoc
->
rwnd_over
||
(
datalen
>
asoc
->
rwnd
+
asoc
->
frag_point
))
{
if
(
asoc
->
rwnd_over
||
(
datalen
>
asoc
->
rwnd
+
asoc
->
frag_point
))
{
/* If this is the next TSN, consider reneging to make
/* There is absolutely no room, but this is the most
* room. Note: Playing nice with a confused sender. A
* important tsn that we are waiting on, try to
* malicious sender can still eat up all our buffer
* to partial deliver or renege to make room.
* space and in the future we may want to detect and
* do more drastic reneging.
*/
*/
if
((
sctp_tsnmap_get_ctsn
(
&
asoc
->
peer
.
tsn_map
)
+
1
)
==
tsn
)
{
if
(
sctp_tsnmap_has_gap
(
&
asoc
->
peer
.
tsn_map
)
&&
deliver
=
SCTP_CMD_CHUNK_PD
;
(
sctp_tsnmap_get_ctsn
(
&
asoc
->
peer
.
tsn_map
)
+
1
)
==
tsn
)
{
SCTP_DEBUG_PRINTK
(
"Reneging for tsn:%u
\n
"
,
tsn
);
deliver
=
SCTP_CMD_RENEGE
;
}
else
{
}
else
{
SCTP_DEBUG_PRINTK
(
"Discard tsn: %u len: %Zd, "
SCTP_DEBUG_PRINTK
(
"Discard tsn: %u len: %Zd, "
"rwnd: %d
\n
"
,
tsn
,
datalen
,
"rwnd: %d
\n
"
,
tsn
,
datalen
,
...
@@ -2379,21 +2385,23 @@ sctp_disposition_t sctp_sf_eat_data_6_2(const sctp_endpoint_t *ep,
...
@@ -2379,21 +2385,23 @@ sctp_disposition_t sctp_sf_eat_data_6_2(const sctp_endpoint_t *ep,
sctp_add_cmd_sf
(
commands
,
SCTP_CMD_DISCARD_PACKET
,
SCTP_NULL
());
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_NULL
());
SCTP_INC_STATS
(
SctpAborteds
);
SCTP_INC_STATS
(
SctpAborteds
);
SCTP_
IN
C_STATS
(
SctpCurrEstab
);
SCTP_
DE
C_STATS
(
SctpCurrEstab
);
return
SCTP_DISPOSITION_CONSUME
;
return
SCTP_DISPOSITION_CONSUME
;
}
}
/* If definately accepting the DATA chunk, record its TSN, otherwise
/* If definately accepting the DATA chunk, record its TSN, otherwise
* wait for renege processing.
* wait for renege processing.
*/
*/
if
(
deliver
!=
SCTP_CMD_CHUNK_PD
)
{
if
(
SCTP_CMD_CHUNK_ULP
==
deliver
)
sctp_add_cmd_sf
(
commands
,
SCTP_CMD_REPORT_TSN
,
SCTP_U32
(
tsn
));
sctp_add_cmd_sf
(
commands
,
SCTP_CMD_REPORT_TSN
,
SCTP_U32
(
tsn
));
/* Note: Some chunks may get overcounted (if we drop) or overcounted
* if we renege and the chunk arrives again.
*/
if
(
chunk
->
chunk_hdr
->
flags
&
SCTP_DATA_UNORDERED
)
if
(
chunk
->
chunk_hdr
->
flags
&
SCTP_DATA_UNORDERED
)
SCTP_INC_STATS
(
SctpInUnorderChunks
);
SCTP_INC_STATS
(
SctpInUnorderChunks
);
else
else
SCTP_INC_STATS
(
SctpInOrderChunks
);
SCTP_INC_STATS
(
SctpInOrderChunks
);
}
/* RFC 2960 6.5 Stream Identifier and Stream Sequence Number
/* RFC 2960 6.5 Stream Identifier and Stream Sequence Number
*
*
...
@@ -2592,7 +2600,7 @@ sctp_disposition_t sctp_sf_eat_data_fast_4_4(const sctp_endpoint_t *ep,
...
@@ -2592,7 +2600,7 @@ sctp_disposition_t sctp_sf_eat_data_fast_4_4(const sctp_endpoint_t *ep,
sctp_add_cmd_sf
(
commands
,
SCTP_CMD_DISCARD_PACKET
,
SCTP_NULL
());
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_NULL
());
SCTP_INC_STATS
(
SctpAborteds
);
SCTP_INC_STATS
(
SctpAborteds
);
SCTP_
IN
C_STATS
(
SctpCurrEstab
);
SCTP_
DE
C_STATS
(
SctpCurrEstab
);
return
SCTP_DISPOSITION_CONSUME
;
return
SCTP_DISPOSITION_CONSUME
;
}
}
...
...
net/sctp/socket.c
View file @
294cb923
...
@@ -2183,6 +2183,50 @@ static inline int sctp_getsockopt_get_local_addrs(struct sock *sk, int len,
...
@@ -2183,6 +2183,50 @@ static inline int sctp_getsockopt_get_local_addrs(struct sock *sk, int len,
return
0
;
return
0
;
}
}
/*
*
* 7.1.15 Set default send parameters (SET_DEFAULT_SEND_PARAM)
*
* Applications that wish to use the sendto() system call may wish to
* specify a default set of parameters that would normally be supplied
* through the inclusion of ancillary data. This socket option allows
* such an application to set the default sctp_sndrcvinfo structure.
* The application that wishes to use this socket option simply passes
* 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
* to this call if the caller is using the UDP model.
*
* For getsockopt, it get the default sctp_sndrcvinfo structure.
*/
static
inline
int
sctp_getsockopt_set_default_send_param
(
struct
sock
*
sk
,
int
len
,
char
*
optval
,
int
*
optlen
)
{
struct
sctp_sndrcvinfo
info
;
sctp_association_t
*
asoc
;
if
(
len
!=
sizeof
(
struct
sctp_sndrcvinfo
))
return
-
EINVAL
;
if
(
copy_from_user
(
&
info
,
optval
,
sizeof
(
struct
sctp_sndrcvinfo
)))
return
-
EFAULT
;
asoc
=
sctp_id2assoc
(
sk
,
info
.
sinfo_assoc_id
);
if
(
!
asoc
)
return
-
EINVAL
;
info
.
sinfo_stream
=
asoc
->
defaults
.
stream
;
info
.
sinfo_flags
=
asoc
->
defaults
.
flags
;
info
.
sinfo_ppid
=
asoc
->
defaults
.
ppid
;
info
.
sinfo_context
=
asoc
->
defaults
.
context
;
info
.
sinfo_timetolive
=
asoc
->
defaults
.
timetolive
;
if
(
copy_to_user
(
optval
,
&
info
,
sizeof
(
struct
sctp_sndrcvinfo
)))
return
-
EFAULT
;
return
0
;
}
SCTP_STATIC
int
sctp_getsockopt
(
struct
sock
*
sk
,
int
level
,
int
optname
,
SCTP_STATIC
int
sctp_getsockopt
(
struct
sock
*
sk
,
int
level
,
int
optname
,
char
*
optval
,
int
*
optlen
)
char
*
optval
,
int
*
optlen
)
{
{
...
@@ -2260,6 +2304,11 @@ SCTP_STATIC int sctp_getsockopt(struct sock *sk, int level, int optname,
...
@@ -2260,6 +2304,11 @@ SCTP_STATIC int sctp_getsockopt(struct sock *sk, int level, int optname,
optlen
);
optlen
);
break
;
break
;
case
SCTP_SET_DEFAULT_SEND_PARAM
:
retval
=
sctp_getsockopt_set_default_send_param
(
sk
,
len
,
optval
,
optlen
);
break
;
default:
default:
retval
=
-
ENOPROTOOPT
;
retval
=
-
ENOPROTOOPT
;
break
;
break
;
...
...
net/sctp/tsnmap.c
View file @
294cb923
...
@@ -385,3 +385,23 @@ static void sctp_tsnmap_find_gap_ack(__u8 *map, __u16 off,
...
@@ -385,3 +385,23 @@ static void sctp_tsnmap_find_gap_ack(__u8 *map, __u16 off,
}
}
}
}
}
}
/* Renege that we have seen a TSN. */
void
sctp_tsnmap_renege
(
struct
sctp_tsnmap
*
map
,
__u32
tsn
)
{
__s32
gap
;
if
(
TSN_lt
(
tsn
,
map
->
base_tsn
))
return
;
if
(
!
TSN_lt
(
tsn
,
map
->
base_tsn
+
map
->
len
+
map
->
len
))
return
;
/* Assert: TSN is in range. */
gap
=
tsn
-
map
->
base_tsn
;
/* Pretend we never saw the TSN. */
if
(
gap
<
map
->
len
)
map
->
tsn_map
[
gap
]
=
0
;
else
map
->
overflow_map
[
gap
-
map
->
len
]
=
0
;
}
net/sctp/ulpqueue.c
View file @
294cb923
...
@@ -655,32 +655,119 @@ static inline struct sctp_ulpevent *sctp_ulpq_order(struct sctp_ulpq *ulpq,
...
@@ -655,32 +655,119 @@ static inline struct sctp_ulpevent *sctp_ulpq_order(struct sctp_ulpq *ulpq,
return
event
;
return
event
;
}
}
/* Renege 'needed' bytes from the ordering queue. */
static
__u16
sctp_ulpq_renege_order
(
struct
sctp_ulpq
*
ulpq
,
__u16
needed
)
{
__u16
freed
=
0
;
__u32
tsn
;
struct
sk_buff
*
skb
;
struct
sctp_ulpevent
*
event
;
struct
sctp_tsnmap
*
tsnmap
;
tsnmap
=
&
ulpq
->
asoc
->
peer
.
tsn_map
;
while
((
skb
=
__skb_dequeue_tail
(
&
ulpq
->
lobby
)))
{
freed
+=
skb_headlen
(
skb
);
event
=
sctp_skb2event
(
skb
);
tsn
=
event
->
sndrcvinfo
.
sinfo_tsn
;
sctp_ulpevent_free
(
event
);
sctp_tsnmap_renege
(
tsnmap
,
tsn
);
if
(
freed
>=
needed
)
return
freed
;
}
return
freed
;
}
/* Renege 'needed' bytes from the reassembly queue. */
static
__u16
sctp_ulpq_renege_frags
(
struct
sctp_ulpq
*
ulpq
,
__u16
needed
)
{
__u16
freed
=
0
;
__u32
tsn
;
struct
sk_buff
*
skb
;
struct
sctp_ulpevent
*
event
;
struct
sctp_tsnmap
*
tsnmap
;
tsnmap
=
&
ulpq
->
asoc
->
peer
.
tsn_map
;
/* Walk backwards through the list, reneges the newest tsns. */
while
((
skb
=
__skb_dequeue_tail
(
&
ulpq
->
reasm
)))
{
freed
+=
skb_headlen
(
skb
);
event
=
sctp_skb2event
(
skb
);
tsn
=
event
->
sndrcvinfo
.
sinfo_tsn
;
sctp_ulpevent_free
(
event
);
sctp_tsnmap_renege
(
tsnmap
,
tsn
);
if
(
freed
>=
needed
)
return
freed
;
}
return
freed
;
}
/* Partial deliver the first message as there is pressure on rwnd. */
/* Partial deliver the first message as there is pressure on rwnd. */
void
sctp_ulpq_partial_delivery
(
struct
sctp_ulpq
*
ulpq
,
void
sctp_ulpq_partial_delivery
(
struct
sctp_ulpq
*
ulpq
,
struct
sctp_chunk
*
chunk
,
int
priority
)
struct
sctp_chunk
*
chunk
,
int
priority
)
{
{
struct
sctp_ulpevent
*
event
;
struct
sctp_ulpevent
*
event
;
struct
sctp_association
*
asoc
;
asoc
=
ulpq
->
asoc
;
/* Are we already in partial delivery mode? */
/* Are we already in partial delivery mode? */
if
(
!
sctp_sk
(
ulpq
->
asoc
->
base
.
sk
)
->
pd_mode
)
{
if
(
!
sctp_sk
(
asoc
->
base
.
sk
)
->
pd_mode
)
{
/* Is partial delivery possible? */
/* Is partial delivery possible? */
event
=
sctp_ulpq_retrieve_first
(
ulpq
);
event
=
sctp_ulpq_retrieve_first
(
ulpq
);
/* Send event to the ULP. */
/* Send event to the ULP. */
if
(
event
)
{
if
(
event
)
{
sctp_ulpq_tail_event
(
ulpq
,
event
);
sctp_ulpq_tail_event
(
ulpq
,
event
);
sctp_sk
(
ulpq
->
asoc
->
base
.
sk
)
->
pd_mode
=
1
;
sctp_sk
(
asoc
->
base
.
sk
)
->
pd_mode
=
1
;
ulpq
->
pd_mode
=
1
;
ulpq
->
pd_mode
=
1
;
return
;
return
;
}
}
}
}
}
/* Assert: Either already in partial delivery mode or partial
/* Renege some packets to make room for an incoming chunk. */
* delivery wasn't possible, so now the only recourse is
void
sctp_ulpq_renege
(
struct
sctp_ulpq
*
ulpq
,
struct
sctp_chunk
*
chunk
,
* to renege. FIXME: Add renege support starts here.
int
priority
)
*/
{
struct
sctp_association
*
asoc
;
__u16
needed
,
freed
;
asoc
=
ulpq
->
asoc
;
if
(
chunk
)
{
needed
=
ntohs
(
chunk
->
chunk_hdr
->
length
);
needed
-=
sizeof
(
sctp_data_chunk_t
);
}
else
needed
=
SCTP_DEFAULT_MAXWINDOW
;
freed
=
0
;
if
(
skb_queue_empty
(
&
asoc
->
base
.
sk
->
receive_queue
))
{
freed
=
sctp_ulpq_renege_order
(
ulpq
,
needed
);
if
(
freed
<
needed
)
{
freed
+=
sctp_ulpq_renege_frags
(
ulpq
,
needed
-
freed
);
}
}
/* If able to free enough room, accept this chunk. */
if
(
chunk
&&
(
freed
>=
needed
))
{
__u32
tsn
;
tsn
=
ntohl
(
chunk
->
subh
.
data_hdr
->
tsn
);
sctp_tsnmap_mark
(
&
asoc
->
peer
.
tsn_map
,
tsn
);
sctp_ulpq_tail_data
(
ulpq
,
chunk
,
priority
);
sctp_ulpq_partial_delivery
(
ulpq
,
chunk
,
priority
);
}
return
;
}
}
/* Notify the application if an association is aborted and in
/* Notify the application if an association is aborted and in
* partial delivery mode. Send up any pending received messages.
* partial delivery mode. Send up any pending received messages.
*/
*/
...
...
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