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
0c336e6d
Commit
0c336e6d
authored
May 01, 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
62dca1b4
c5d01dcf
Changes
8
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
119 additions
and
60 deletions
+119
-60
include/net/sctp/structs.h
include/net/sctp/structs.h
+25
-18
net/sctp/chunk.c
net/sctp/chunk.c
+43
-7
net/sctp/output.c
net/sctp/output.c
+3
-0
net/sctp/outqueue.c
net/sctp/outqueue.c
+24
-25
net/sctp/sm_make_chunk.c
net/sctp/sm_make_chunk.c
+1
-1
net/sctp/sm_statefuns.c
net/sctp/sm_statefuns.c
+2
-1
net/sctp/socket.c
net/sctp/socket.c
+9
-6
net/sctp/ulpevent.c
net/sctp/ulpevent.c
+12
-2
No files found.
include/net/sctp/structs.h
View file @
0c336e6d
...
@@ -450,7 +450,7 @@ static inline __u16 sctp_ssn_next(struct sctp_stream *stream, __u16 id)
...
@@ -450,7 +450,7 @@ static inline __u16 sctp_ssn_next(struct sctp_stream *stream, __u16 id)
}
}
/* Structure to track chunk fragments that have been acked, but peer
/* Structure to track chunk fragments that have been acked, but peer
* fragments of the same message have not.
* fragments of the same message have not.
*/
*/
struct
sctp_datamsg
{
struct
sctp_datamsg
{
/* Chunks waiting to be submitted to lower layer. */
/* Chunks waiting to be submitted to lower layer. */
...
@@ -459,9 +459,13 @@ struct sctp_datamsg {
...
@@ -459,9 +459,13 @@ struct sctp_datamsg {
struct
list_head
track
;
struct
list_head
track
;
/* Reference counting. */
/* Reference counting. */
atomic_t
refcnt
;
atomic_t
refcnt
;
/* When is this message no longer interesting to the peer? */
unsigned
long
expires_at
;
/* Did the messenge fail to send? */
/* Did the messenge fail to send? */
int
send_error
;
int
send_error
;
char
send_failed
;
char
send_failed
;
/* Control whether fragments from this message can expire. */
char
can_expire
;
};
};
struct
sctp_datamsg
*
sctp_datamsg_from_user
(
struct
sctp_association
*
,
struct
sctp_datamsg
*
sctp_datamsg_from_user
(
struct
sctp_association
*
,
...
@@ -473,6 +477,9 @@ void sctp_datamsg_hold(struct sctp_datamsg *);
...
@@ -473,6 +477,9 @@ void sctp_datamsg_hold(struct sctp_datamsg *);
void
sctp_datamsg_free
(
struct
sctp_datamsg
*
);
void
sctp_datamsg_free
(
struct
sctp_datamsg
*
);
void
sctp_datamsg_track
(
struct
sctp_chunk
*
);
void
sctp_datamsg_track
(
struct
sctp_chunk
*
);
void
sctp_datamsg_assign
(
struct
sctp_datamsg
*
,
struct
sctp_chunk
*
);
void
sctp_datamsg_assign
(
struct
sctp_datamsg
*
,
struct
sctp_chunk
*
);
void
sctp_datamsg_fail
(
struct
sctp_chunk
*
,
int
error
);
int
sctp_datamsg_expires
(
struct
sctp_chunk
*
);
/* RFC2960 1.4 Key Terms
/* RFC2960 1.4 Key Terms
*
*
...
@@ -545,18 +552,6 @@ struct sctp_chunk {
...
@@ -545,18 +552,6 @@ struct sctp_chunk {
/* We fill this in if we are calculating RTT. */
/* We fill this in if we are calculating RTT. */
unsigned
long
sent_at
;
unsigned
long
sent_at
;
__u8
rtt_in_progress
;
/* Is this chunk used for RTT calculation? */
__u8
resent
;
/* Has this chunk ever been retransmitted. */
__u8
has_tsn
;
/* Does this chunk have a TSN yet? */
__u8
has_ssn
;
/* Does this chunk have a SSN yet? */
__u8
singleton
;
/* Was this the only chunk in the packet? */
__u8
end_of_packet
;
/* Was this the last chunk in the packet? */
__u8
ecn_ce_done
;
/* Have we processed the ECN CE bit? */
__u8
pdiscard
;
/* Discard the whole packet now? */
__u8
tsn_gap_acked
;
/* Is this chunk acked by a GAP ACK? */
__u8
fast_retransmit
;
/* Is this chunk fast retransmitted? */
__u8
tsn_missing_report
;
/* Data chunk missing counter. */
/* What is the origin IP address for this chunk? */
/* What is the origin IP address for this chunk? */
union
sctp_addr
source
;
union
sctp_addr
source
;
/* Destination address for this chunk. */
/* Destination address for this chunk. */
...
@@ -570,6 +565,18 @@ struct sctp_chunk {
...
@@ -570,6 +565,18 @@ struct sctp_chunk {
* go. It is NULL if we have no preference.
* go. It is NULL if we have no preference.
*/
*/
struct
sctp_transport
*
transport
;
struct
sctp_transport
*
transport
;
__u8
rtt_in_progress
;
/* Is this chunk used for RTT calculation? */
__u8
resent
;
/* Has this chunk ever been retransmitted. */
__u8
has_tsn
;
/* Does this chunk have a TSN yet? */
__u8
has_ssn
;
/* Does this chunk have a SSN yet? */
__u8
singleton
;
/* Was this the only chunk in the packet? */
__u8
end_of_packet
;
/* Was this the last chunk in the packet? */
__u8
ecn_ce_done
;
/* Have we processed the ECN CE bit? */
__u8
pdiscard
;
/* Discard the whole packet now? */
__u8
tsn_gap_acked
;
/* Is this chunk acked by a GAP ACK? */
__u8
fast_retransmit
;
/* Is this chunk fast retransmitted? */
__u8
tsn_missing_report
;
/* Data chunk missing counter. */
};
};
void
sctp_chunk_hold
(
struct
sctp_chunk
*
);
void
sctp_chunk_hold
(
struct
sctp_chunk
*
);
...
@@ -580,10 +587,10 @@ struct sctp_chunk *sctp_make_chunk(const struct sctp_association *, __u8 type,
...
@@ -580,10 +587,10 @@ struct sctp_chunk *sctp_make_chunk(const struct sctp_association *, __u8 type,
__u8
flags
,
int
size
);
__u8
flags
,
int
size
);
void
sctp_chunk_free
(
struct
sctp_chunk
*
);
void
sctp_chunk_free
(
struct
sctp_chunk
*
);
void
*
sctp_addto_chunk
(
struct
sctp_chunk
*
,
int
len
,
const
void
*
data
);
void
*
sctp_addto_chunk
(
struct
sctp_chunk
*
,
int
len
,
const
void
*
data
);
struct
sctp_chunk
*
sctp_chunkify
(
struct
sk_buff
*
,
struct
sctp_chunk
*
sctp_chunkify
(
struct
sk_buff
*
,
const
struct
sctp_association
*
,
const
struct
sctp_association
*
,
struct
sock
*
);
struct
sock
*
);
void
sctp_init_addrs
(
struct
sctp_chunk
*
,
union
sctp_addr
*
,
void
sctp_init_addrs
(
struct
sctp_chunk
*
,
union
sctp_addr
*
,
union
sctp_addr
*
);
union
sctp_addr
*
);
const
union
sctp_addr
*
sctp_source
(
const
struct
sctp_chunk
*
chunk
);
const
union
sctp_addr
*
sctp_source
(
const
struct
sctp_chunk
*
chunk
);
...
@@ -847,7 +854,7 @@ struct sctp_transport {
...
@@ -847,7 +854,7 @@ struct sctp_transport {
/* A flag which indicates the occurrence of a changeover */
/* A flag which indicates the occurrence of a changeover */
char
changeover_active
;
char
changeover_active
;
/* A glag which indicates whether the change of primary is
/* A glag which indicates whether the change of primary is
* the first switch to this destination address during an
* the first switch to this destination address during an
* active switch.
* active switch.
...
@@ -1024,7 +1031,7 @@ struct sctp_bind_addr {
...
@@ -1024,7 +1031,7 @@ struct sctp_bind_addr {
struct
sctp_bind_addr
*
sctp_bind_addr_new
(
int
gfp_mask
);
struct
sctp_bind_addr
*
sctp_bind_addr_new
(
int
gfp_mask
);
void
sctp_bind_addr_init
(
struct
sctp_bind_addr
*
,
__u16
port
);
void
sctp_bind_addr_init
(
struct
sctp_bind_addr
*
,
__u16
port
);
void
sctp_bind_addr_free
(
struct
sctp_bind_addr
*
);
void
sctp_bind_addr_free
(
struct
sctp_bind_addr
*
);
int
sctp_bind_addr_copy
(
struct
sctp_bind_addr
*
dest
,
int
sctp_bind_addr_copy
(
struct
sctp_bind_addr
*
dest
,
const
struct
sctp_bind_addr
*
src
,
const
struct
sctp_bind_addr
*
src
,
sctp_scope_t
scope
,
int
gfp
,
int
flags
);
sctp_scope_t
scope
,
int
gfp
,
int
flags
);
int
sctp_add_bind_addr
(
struct
sctp_bind_addr
*
,
union
sctp_addr
*
,
int
sctp_add_bind_addr
(
struct
sctp_bind_addr
*
,
union
sctp_addr
*
,
...
@@ -1613,7 +1620,7 @@ struct sctp_association {
...
@@ -1613,7 +1620,7 @@ struct sctp_association {
/* Need to send an ECNE Chunk? */
/* Need to send an ECNE Chunk? */
char
need_ecne
;
char
need_ecne
;
/* Is it a temporary association? */
/* Is it a temporary association? */
char
temp
;
char
temp
;
};
};
...
...
net/sctp/chunk.c
View file @
0c336e6d
...
@@ -55,8 +55,8 @@ void sctp_datamsg_init(struct sctp_datamsg *msg)
...
@@ -55,8 +55,8 @@ void sctp_datamsg_init(struct sctp_datamsg *msg)
atomic_set
(
&
msg
->
refcnt
,
1
);
atomic_set
(
&
msg
->
refcnt
,
1
);
msg
->
send_failed
=
0
;
msg
->
send_failed
=
0
;
msg
->
send_error
=
0
;
msg
->
send_error
=
0
;
msg
->
can_expire
=
0
;
INIT_LIST_HEAD
(
&
msg
->
chunks
);
INIT_LIST_HEAD
(
&
msg
->
chunks
);
INIT_LIST_HEAD
(
&
msg
->
track
);
}
}
/* Allocate and initialize datamsg. */
/* Allocate and initialize datamsg. */
...
@@ -84,7 +84,7 @@ static void sctp_datamsg_destroy(struct sctp_datamsg *msg)
...
@@ -84,7 +84,7 @@ static void sctp_datamsg_destroy(struct sctp_datamsg *msg)
notify
=
msg
->
send_failed
?
-
1
:
0
;
notify
=
msg
->
send_failed
?
-
1
:
0
;
/* Release all references. */
/* Release all references. */
list_for_each_safe
(
pos
,
temp
,
&
msg
->
track
)
{
list_for_each_safe
(
pos
,
temp
,
&
msg
->
chunks
)
{
list_del
(
pos
);
list_del
(
pos
);
chunk
=
list_entry
(
pos
,
struct
sctp_chunk
,
frag_list
);
chunk
=
list_entry
(
pos
,
struct
sctp_chunk
,
frag_list
);
/* Check whether we _really_ need to notify. */
/* Check whether we _really_ need to notify. */
...
@@ -94,7 +94,7 @@ static void sctp_datamsg_destroy(struct sctp_datamsg *msg)
...
@@ -94,7 +94,7 @@ static void sctp_datamsg_destroy(struct sctp_datamsg *msg)
error
=
msg
->
send_error
;
error
=
msg
->
send_error
;
else
else
error
=
asoc
->
outqueue
.
error
;
error
=
asoc
->
outqueue
.
error
;
sp
=
sctp_sk
(
asoc
->
base
.
sk
);
sp
=
sctp_sk
(
asoc
->
base
.
sk
);
notify
=
sctp_ulpevent_type_enabled
(
SCTP_SEND_FAILED
,
notify
=
sctp_ulpevent_type_enabled
(
SCTP_SEND_FAILED
,
&
sp
->
subscribe
);
&
sp
->
subscribe
);
...
@@ -107,8 +107,8 @@ static void sctp_datamsg_destroy(struct sctp_datamsg *msg)
...
@@ -107,8 +107,8 @@ static void sctp_datamsg_destroy(struct sctp_datamsg *msg)
sent
=
SCTP_DATA_SENT
;
sent
=
SCTP_DATA_SENT
;
else
else
sent
=
SCTP_DATA_UNSENT
;
sent
=
SCTP_DATA_UNSENT
;
ev
=
sctp_ulpevent_make_send_failed
(
asoc
,
chunk
,
sent
,
ev
=
sctp_ulpevent_make_send_failed
(
asoc
,
chunk
,
sent
,
error
,
GFP_ATOMIC
);
error
,
GFP_ATOMIC
);
if
(
ev
)
if
(
ev
)
sctp_ulpq_tail_event
(
&
asoc
->
ulpq
,
ev
);
sctp_ulpq_tail_event
(
&
asoc
->
ulpq
,
ev
);
...
@@ -146,7 +146,6 @@ void sctp_datamsg_free(struct sctp_datamsg *msg)
...
@@ -146,7 +146,6 @@ void sctp_datamsg_free(struct sctp_datamsg *msg)
void
sctp_datamsg_track
(
struct
sctp_chunk
*
chunk
)
void
sctp_datamsg_track
(
struct
sctp_chunk
*
chunk
)
{
{
sctp_chunk_hold
(
chunk
);
sctp_chunk_hold
(
chunk
);
list_add_tail
(
&
chunk
->
frag_list
,
&
chunk
->
msg
->
track
);
}
}
/* Assign a chunk to this datamsg. */
/* Assign a chunk to this datamsg. */
...
@@ -179,6 +178,20 @@ struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *asoc,
...
@@ -179,6 +178,20 @@ struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *asoc,
if
(
!
msg
)
if
(
!
msg
)
return
NULL
;
return
NULL
;
/* Note: Calculate this outside of the loop, so that all fragments
* have the same expiration.
*/
if
(
sinfo
->
sinfo_timetolive
)
{
struct
timeval
tv
;
__u32
ttl
=
sinfo
->
sinfo_timetolive
;
/* sinfo_timetolive is in milliseconds */
tv
.
tv_sec
=
ttl
/
1000
;
tv
.
tv_usec
=
ttl
%
1000
*
1000
;
msg
->
expires_at
=
jiffies
+
timeval_to_jiffies
(
&
tv
);
msg
->
can_expire
=
1
;
}
/* What is a reasonable fragmentation point right now? */
/* What is a reasonable fragmentation point right now? */
max
=
asoc
->
pmtu
;
max
=
asoc
->
pmtu
;
if
(
max
<
SCTP_MIN_PMTU
)
if
(
max
<
SCTP_MIN_PMTU
)
...
@@ -191,7 +204,6 @@ struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *asoc,
...
@@ -191,7 +204,6 @@ struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *asoc,
/* Subtract out the overhead of a data chunk header. */
/* Subtract out the overhead of a data chunk header. */
max
-=
sizeof
(
struct
sctp_data_chunk
);
max
-=
sizeof
(
struct
sctp_data_chunk
);
whole
=
0
;
whole
=
0
;
/* If user has specified smaller fragmentation, make it so. */
/* If user has specified smaller fragmentation, make it so. */
...
@@ -289,3 +301,27 @@ struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *asoc,
...
@@ -289,3 +301,27 @@ struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *asoc,
sctp_datamsg_free
(
msg
);
sctp_datamsg_free
(
msg
);
return
NULL
;
return
NULL
;
}
}
/* Check whether this message has expired. */
int
sctp_datamsg_expires
(
struct
sctp_chunk
*
chunk
)
{
struct
sctp_datamsg
*
msg
=
chunk
->
msg
;
/* FIXME: When PR-SCTP is supported we can make this
* check more lenient.
*/
if
(
!
msg
->
can_expire
)
return
0
;
if
(
time_after
(
jiffies
,
msg
->
expires_at
))
return
1
;
return
0
;
}
/* This chunk (and consequently entire message) has failed in its sending. */
void
sctp_datamsg_fail
(
struct
sctp_chunk
*
chunk
,
int
error
)
{
chunk
->
msg
->
send_failed
=
1
;
chunk
->
msg
->
send_error
=
error
;
}
net/sctp/output.c
View file @
0c336e6d
...
@@ -356,6 +356,7 @@ int sctp_packet_transmit(struct sctp_packet *packet)
...
@@ -356,6 +356,7 @@ int sctp_packet_transmit(struct sctp_packet *packet)
if
(
sctp_chunk_is_data
(
chunk
))
{
if
(
sctp_chunk_is_data
(
chunk
))
{
if
(
!
chunk
->
has_tsn
)
{
if
(
!
chunk
->
has_tsn
)
{
sctp_chunk_assign_ssn
(
chunk
);
sctp_chunk_assign_tsn
(
chunk
);
sctp_chunk_assign_tsn
(
chunk
);
/* 6.3.1 C4) When data is in flight and when allowed
/* 6.3.1 C4) When data is in flight and when allowed
...
@@ -627,6 +628,8 @@ static sctp_xmit_t sctp_packet_append_data(struct sctp_packet *packet,
...
@@ -627,6 +628,8 @@ static sctp_xmit_t sctp_packet_append_data(struct sctp_packet *packet,
rwnd
=
0
;
rwnd
=
0
;
asoc
->
peer
.
rwnd
=
rwnd
;
asoc
->
peer
.
rwnd
=
rwnd
;
/* Has been accepted for transmission. */
chunk
->
msg
->
can_expire
=
0
;
finish:
finish:
return
retval
;
return
retval
;
...
...
net/sctp/outqueue.c
View file @
0c336e6d
...
@@ -165,7 +165,7 @@ static inline int sctp_cacc_skip_3_1(struct sctp_transport *primary,
...
@@ -165,7 +165,7 @@ static inline int sctp_cacc_skip_3_1(struct sctp_transport *primary,
*/
*/
static
inline
int
sctp_cacc_skip_3_2
(
struct
sctp_transport
*
primary
,
__u32
tsn
)
static
inline
int
sctp_cacc_skip_3_2
(
struct
sctp_transport
*
primary
,
__u32
tsn
)
{
{
if
(
primary
->
cacc
.
cycling_changeover
&&
if
(
primary
->
cacc
.
cycling_changeover
&&
TSN_lt
(
tsn
,
primary
->
cacc
.
next_tsn_at_change
))
TSN_lt
(
tsn
,
primary
->
cacc
.
next_tsn_at_change
))
return
1
;
return
1
;
return
0
;
return
0
;
...
@@ -174,7 +174,7 @@ static inline int sctp_cacc_skip_3_2(struct sctp_transport *primary, __u32 tsn)
...
@@ -174,7 +174,7 @@ static inline int sctp_cacc_skip_3_2(struct sctp_transport *primary, __u32 tsn)
/*
/*
* SFR-CACC algorithm:
* SFR-CACC algorithm:
* 3) If the missing report count for TSN t is to be
* 3) If the missing report count for TSN t is to be
* incremented according to [RFC2960] and
* incremented according to [RFC2960] and
* [SCTP_STEWART-2002], and CHANGEOVER_ACTIVE is set,
* [SCTP_STEWART-2002], and CHANGEOVER_ACTIVE is set,
* then the sender MUST futher execute steps 3.1 and
* then the sender MUST futher execute steps 3.1 and
* 3.2 to determine if the missing report count for
* 3.2 to determine if the missing report count for
...
@@ -251,8 +251,7 @@ void sctp_outq_teardown(struct sctp_outq *q)
...
@@ -251,8 +251,7 @@ void sctp_outq_teardown(struct sctp_outq *q)
chunk
=
list_entry
(
lchunk
,
struct
sctp_chunk
,
chunk
=
list_entry
(
lchunk
,
struct
sctp_chunk
,
transmitted_list
);
transmitted_list
);
/* Mark as part of a failed message. */
/* Mark as part of a failed message. */
chunk
->
msg
->
send_failed
=
1
;
sctp_datamsg_fail
(
chunk
,
q
->
error
);
/* Generate a SEND FAILED event. */
sctp_chunk_free
(
chunk
);
sctp_chunk_free
(
chunk
);
}
}
}
}
...
@@ -262,6 +261,7 @@ void sctp_outq_teardown(struct sctp_outq *q)
...
@@ -262,6 +261,7 @@ void sctp_outq_teardown(struct sctp_outq *q)
list_del
(
lchunk
);
list_del
(
lchunk
);
chunk
=
list_entry
(
lchunk
,
struct
sctp_chunk
,
chunk
=
list_entry
(
lchunk
,
struct
sctp_chunk
,
transmitted_list
);
transmitted_list
);
sctp_datamsg_fail
(
chunk
,
q
->
error
);
sctp_chunk_free
(
chunk
);
sctp_chunk_free
(
chunk
);
}
}
...
@@ -270,6 +270,7 @@ void sctp_outq_teardown(struct sctp_outq *q)
...
@@ -270,6 +270,7 @@ void sctp_outq_teardown(struct sctp_outq *q)
list_del
(
lchunk
);
list_del
(
lchunk
);
chunk
=
list_entry
(
lchunk
,
struct
sctp_chunk
,
chunk
=
list_entry
(
lchunk
,
struct
sctp_chunk
,
transmitted_list
);
transmitted_list
);
sctp_datamsg_fail
(
chunk
,
q
->
error
);
sctp_chunk_free
(
chunk
);
sctp_chunk_free
(
chunk
);
}
}
...
@@ -277,7 +278,7 @@ void sctp_outq_teardown(struct sctp_outq *q)
...
@@ -277,7 +278,7 @@ void sctp_outq_teardown(struct sctp_outq *q)
while
((
chunk
=
sctp_outq_dequeue_data
(
q
)))
{
while
((
chunk
=
sctp_outq_dequeue_data
(
q
)))
{
/* Mark as send failure. */
/* Mark as send failure. */
chunk
->
msg
->
send_failed
=
1
;
sctp_datamsg_fail
(
chunk
,
q
->
error
)
;
sctp_chunk_free
(
chunk
);
sctp_chunk_free
(
chunk
);
}
}
...
@@ -800,27 +801,25 @@ int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout)
...
@@ -800,27 +801,25 @@ int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout)
*/
*/
if
(
chunk
->
sinfo
.
sinfo_stream
>=
if
(
chunk
->
sinfo
.
sinfo_stream
>=
asoc
->
c
.
sinit_num_ostreams
)
{
asoc
->
c
.
sinit_num_ostreams
)
{
/* Mark as failed send. */
chunk
->
msg
->
send_failed
=
1
;
chunk
->
msg
->
send_error
=
SCTP_ERROR_INV_STRM
;
/* Free the chunk. */
/* Mark as s failed send. */
sctp_datamsg_fail
(
chunk
,
SCTP_ERROR_INV_STRM
);
sctp_chunk_free
(
chunk
);
sctp_chunk_free
(
chunk
);
continue
;
continue
;
}
}
/* Now do delayed assignment of SSN. This will
/* Has this chunk expired? */
* probably change again when we start supporting
if
(
sctp_datamsg_expires
(
chunk
))
{
* large (> approximately 2^16) size messages.
sctp_datamsg_fail
(
chunk
,
0
);
*/
sctp_chunk_free
(
chunk
);
sctp_chunk_assign_ssn
(
chunk
);
continue
;
}
/* If there is a specified transport, use it.
/* If there is a specified transport, use it.
* Otherwise, we want to use the active path.
* Otherwise, we want to use the active path.
*/
*/
new_transport
=
chunk
->
transport
;
new_transport
=
chunk
->
transport
;
if
(
new_transport
==
NULL
||
if
(
!
new_transport
||
!
new_transport
->
active
)
!
new_transport
->
active
)
new_transport
=
asoc
->
peer
.
active_path
;
new_transport
=
asoc
->
peer
.
active_path
;
/* Change packets if necessary. */
/* Change packets if necessary. */
...
@@ -1024,10 +1023,10 @@ int sctp_outq_sack(struct sctp_outq *q, struct sctp_sackhdr *sack)
...
@@ -1024,10 +1023,10 @@ int sctp_outq_sack(struct sctp_outq *q, struct sctp_sackhdr *sack)
/*
/*
* SFR-CACC algorithm:
* SFR-CACC algorithm:
* On receipt of a SACK the sender SHOULD execute the
* On receipt of a SACK the sender SHOULD execute the
* following statements.
* following statements.
*
*
* 1) If the cumulative ack in the SACK passes next tsn_at_change
* 1) If the cumulative ack in the SACK passes next tsn_at_change
* on the current primary, the CHANGEOVER_ACTIVE flag SHOULD be
* on the current primary, the CHANGEOVER_ACTIVE flag SHOULD be
* cleared. The CYCLING_CHANGEOVER flag SHOULD also be cleared for
* cleared. The CYCLING_CHANGEOVER flag SHOULD also be cleared for
* all destinations.
* all destinations.
...
@@ -1041,7 +1040,7 @@ int sctp_outq_sack(struct sctp_outq *q, struct sctp_sackhdr *sack)
...
@@ -1041,7 +1040,7 @@ int sctp_outq_sack(struct sctp_outq *q, struct sctp_sackhdr *sack)
}
}
}
}
/*
/*
* SFR-CACC algorithm:
* SFR-CACC algorithm:
* 2) If the SACK contains gap acks and the flag CHANGEOVER_ACTIVE
* 2) If the SACK contains gap acks and the flag CHANGEOVER_ACTIVE
* is set the receiver of the SACK MUST take the following actions:
* is set the receiver of the SACK MUST take the following actions:
...
@@ -1087,7 +1086,7 @@ int sctp_outq_sack(struct sctp_outq *q, struct sctp_sackhdr *sack)
...
@@ -1087,7 +1086,7 @@ int sctp_outq_sack(struct sctp_outq *q, struct sctp_sackhdr *sack)
transport
,
sack
,
highest_new_tsn
);
transport
,
sack
,
highest_new_tsn
);
/*
/*
* SFR-CACC algorithm:
* SFR-CACC algorithm:
* C) Let count_of_newacks be the number of
* C) Let count_of_newacks be the number of
* destinations for which cacc_saw_newack is set.
* destinations for which cacc_saw_newack is set.
*/
*/
if
(
transport
->
cacc
.
cacc_saw_newack
)
if
(
transport
->
cacc
.
cacc_saw_newack
)
...
@@ -1097,7 +1096,7 @@ int sctp_outq_sack(struct sctp_outq *q, struct sctp_sackhdr *sack)
...
@@ -1097,7 +1096,7 @@ int sctp_outq_sack(struct sctp_outq *q, struct sctp_sackhdr *sack)
list_for_each
(
pos
,
transport_list
)
{
list_for_each
(
pos
,
transport_list
)
{
transport
=
list_entry
(
pos
,
struct
sctp_transport
,
transport
=
list_entry
(
pos
,
struct
sctp_transport
,
transports
);
transports
);
sctp_mark_missing
(
q
,
&
transport
->
transmitted
,
transport
,
sctp_mark_missing
(
q
,
&
transport
->
transmitted
,
transport
,
highest_new_tsn
,
count_of_newacks
);
highest_new_tsn
,
count_of_newacks
);
}
}
...
@@ -1275,8 +1274,8 @@ static void sctp_check_transmitted(struct sctp_outq *q,
...
@@ -1275,8 +1274,8 @@ static void sctp_check_transmitted(struct sctp_outq *q,
* the destination that the TSN was
* the destination that the TSN was
* sent to.
* sent to.
*/
*/
if
(
transport
&&
if
(
transport
&&
sack
->
num_gap_ack_blocks
&&
sack
->
num_gap_ack_blocks
&&
q
->
asoc
->
peer
.
primary_path
->
cacc
.
q
->
asoc
->
peer
.
primary_path
->
cacc
.
changeover_active
)
changeover_active
)
transport
->
cacc
.
cacc_saw_newack
transport
->
cacc
.
cacc_saw_newack
...
@@ -1529,12 +1528,12 @@ static void sctp_mark_missing(struct sctp_outq *q,
...
@@ -1529,12 +1528,12 @@ static void sctp_mark_missing(struct sctp_outq *q,
TSN_lt
(
tsn
,
highest_new_tsn_in_sack
))
{
TSN_lt
(
tsn
,
highest_new_tsn_in_sack
))
{
/* SFR-CACC may require us to skip marking
/* SFR-CACC may require us to skip marking
* this chunk as missing.
* this chunk as missing.
*/
*/
if
(
!
transport
||
!
sctp_cacc_skip
(
primary
,
transport
,
if
(
!
transport
||
!
sctp_cacc_skip
(
primary
,
transport
,
count_of_newacks
,
tsn
))
{
count_of_newacks
,
tsn
))
{
chunk
->
tsn_missing_report
++
;
chunk
->
tsn_missing_report
++
;
SCTP_DEBUG_PRINTK
(
SCTP_DEBUG_PRINTK
(
"%s: TSN 0x%x missing counter: %d
\n
"
,
"%s: TSN 0x%x missing counter: %d
\n
"
,
__FUNCTION__
,
tsn
,
__FUNCTION__
,
tsn
,
...
...
net/sctp/sm_make_chunk.c
View file @
0c336e6d
...
@@ -992,7 +992,7 @@ struct sctp_chunk *sctp_chunkify(struct sk_buff *skb,
...
@@ -992,7 +992,7 @@ struct sctp_chunk *sctp_chunkify(struct sk_buff *skb,
retval
->
has_tsn
=
0
;
retval
->
has_tsn
=
0
;
retval
->
has_ssn
=
0
;
retval
->
has_ssn
=
0
;
retval
->
rtt_in_progress
=
0
;
retval
->
rtt_in_progress
=
0
;
retval
->
sent_at
=
jiffies
;
retval
->
sent_at
=
0
;
retval
->
singleton
=
1
;
retval
->
singleton
=
1
;
retval
->
end_of_packet
=
0
;
retval
->
end_of_packet
=
0
;
retval
->
ecn_ce_done
=
0
;
retval
->
ecn_ce_done
=
0
;
...
...
net/sctp/sm_statefuns.c
View file @
0c336e6d
...
@@ -2372,7 +2372,8 @@ sctp_disposition_t sctp_sf_eat_data_6_2(const struct sctp_endpoint *ep,
...
@@ -2372,7 +2372,8 @@ sctp_disposition_t sctp_sf_eat_data_6_2(const struct sctp_endpoint *ep,
* PMTU. In cases, such as loopback, this might be a rather
* PMTU. In cases, such as loopback, this might be a rather
* large spill over.
* large spill over.
*/
*/
if
(
asoc
->
rwnd_over
||
(
datalen
>
asoc
->
rwnd
+
asoc
->
frag_point
))
{
if
(
!
asoc
->
rwnd
||
asoc
->
rwnd_over
||
(
datalen
>
asoc
->
rwnd
+
asoc
->
frag_point
))
{
/* If this is the next TSN, consider reneging to make
/* If this is the next TSN, consider reneging to make
* room. Note: Playing nice with a confused sender. A
* room. Note: Playing nice with a confused sender. A
...
...
net/sctp/socket.c
View file @
0c336e6d
...
@@ -826,7 +826,7 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk,
...
@@ -826,7 +826,7 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk,
long
timeo
;
long
timeo
;
__u16
sinfo_flags
=
0
;
__u16
sinfo_flags
=
0
;
struct
sctp_datamsg
*
datamsg
;
struct
sctp_datamsg
*
datamsg
;
struct
list_head
*
pos
,
*
temp
;
struct
list_head
*
pos
;
int
msg_flags
=
msg
->
msg_flags
;
int
msg_flags
=
msg
->
msg_flags
;
SCTP_DEBUG_PRINTK
(
"sctp_sendmsg(sk: %p, msg: %p, msg_len: %d)
\n
"
,
SCTP_DEBUG_PRINTK
(
"sctp_sendmsg(sk: %p, msg: %p, msg_len: %d)
\n
"
,
...
@@ -1133,9 +1133,8 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk,
...
@@ -1133,9 +1133,8 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk,
}
}
/* Now send the (possibly) fragmented message. */
/* Now send the (possibly) fragmented message. */
list_for_each
_safe
(
pos
,
temp
,
&
datamsg
->
chunks
)
{
list_for_each
(
pos
,
&
datamsg
->
chunks
)
{
chunk
=
list_entry
(
pos
,
struct
sctp_chunk
,
frag_list
);
chunk
=
list_entry
(
pos
,
struct
sctp_chunk
,
frag_list
);
list_del_init
(
pos
);
sctp_datamsg_track
(
chunk
);
sctp_datamsg_track
(
chunk
);
/* Do accounting for the write space. */
/* Do accounting for the write space. */
...
@@ -1143,7 +1142,11 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk,
...
@@ -1143,7 +1142,11 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk,
chunk
->
transport
=
chunk_tp
;
chunk
->
transport
=
chunk_tp
;
/* Send it to the lower layers. */
/* Send it to the lower layers. Note: all chunks
* must either fail or succeed. The lower layer
* works that way today. Keep it that way or this
* breaks.
*/
err
=
sctp_primitive_SEND
(
asoc
,
chunk
);
err
=
sctp_primitive_SEND
(
asoc
,
chunk
);
/* Did the lower layer accept the chunk? */
/* Did the lower layer accept the chunk? */
if
(
err
)
if
(
err
)
...
@@ -1152,7 +1155,7 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk,
...
@@ -1152,7 +1155,7 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk,
}
}
sctp_datamsg_free
(
datamsg
);
sctp_datamsg_free
(
datamsg
);
if
(
err
)
if
(
err
)
goto
out_free
;
goto
out_free
;
else
else
err
=
msg_len
;
err
=
msg_len
;
...
@@ -3815,7 +3818,7 @@ static void sctp_sock_migrate(struct sock *oldsk, struct sock *newsk,
...
@@ -3815,7 +3818,7 @@ static void sctp_sock_migrate(struct sock *oldsk, struct sock *newsk,
/* If the association on the newsk is already closed before accept()
/* If the association on the newsk is already closed before accept()
* is called, set RCV_SHUTDOWN flag.
* is called, set RCV_SHUTDOWN flag.
*/
*/
if
(
sctp_state
(
assoc
,
CLOSED
)
&&
sctp_style
(
newsk
,
TCP
))
if
(
sctp_state
(
assoc
,
CLOSED
)
&&
sctp_style
(
newsk
,
TCP
))
newsk
->
shutdown
|=
RCV_SHUTDOWN
;
newsk
->
shutdown
|=
RCV_SHUTDOWN
;
...
...
net/sctp/ulpevent.c
View file @
0c336e6d
...
@@ -425,6 +425,9 @@ struct sctp_ulpevent *sctp_ulpevent_make_send_failed(
...
@@ -425,6 +425,9 @@ struct sctp_ulpevent *sctp_ulpevent_make_send_failed(
struct
sctp_send_failed
*
ssf
;
struct
sctp_send_failed
*
ssf
;
struct
sk_buff
*
skb
;
struct
sk_buff
*
skb
;
/* Pull off any padding. */
int
len
=
ntohs
(
chunk
->
chunk_hdr
->
length
);
/* Make skb with more room so we can prepend notification. */
/* Make skb with more room so we can prepend notification. */
skb
=
skb_copy_expand
(
chunk
->
skb
,
skb
=
skb_copy_expand
(
chunk
->
skb
,
sizeof
(
struct
sctp_send_failed
),
/* headroom */
sizeof
(
struct
sctp_send_failed
),
/* headroom */
...
@@ -434,7 +437,8 @@ struct sctp_ulpevent *sctp_ulpevent_make_send_failed(
...
@@ -434,7 +437,8 @@ struct sctp_ulpevent *sctp_ulpevent_make_send_failed(
goto
fail
;
goto
fail
;
/* Pull off the common chunk header and DATA header. */
/* Pull off the common chunk header and DATA header. */
skb_pull
(
skb
,
sizeof
(
sctp_data_chunk_t
));
skb_pull
(
skb
,
sizeof
(
struct
sctp_data_chunk
));
len
-=
sizeof
(
struct
sctp_data_chunk
);
/* Embed the event fields inside the cloned skb. */
/* Embed the event fields inside the cloned skb. */
event
=
sctp_skb2event
(
skb
);
event
=
sctp_skb2event
(
skb
);
...
@@ -475,7 +479,8 @@ struct sctp_ulpevent *sctp_ulpevent_make_send_failed(
...
@@ -475,7 +479,8 @@ struct sctp_ulpevent *sctp_ulpevent_make_send_failed(
* This field is the total length of the notification data, including
* This field is the total length of the notification data, including
* the notification header.
* the notification header.
*/
*/
ssf
->
ssf_length
=
skb
->
len
;
ssf
->
ssf_length
=
sizeof
(
struct
sctp_send_failed
)
+
len
;
skb_trim
(
skb
,
ssf
->
ssf_length
);
/* Socket Extensions for SCTP
/* Socket Extensions for SCTP
* 5.3.1.4 SCTP_SEND_FAILED
* 5.3.1.4 SCTP_SEND_FAILED
...
@@ -496,6 +501,11 @@ struct sctp_ulpevent *sctp_ulpevent_make_send_failed(
...
@@ -496,6 +501,11 @@ struct sctp_ulpevent *sctp_ulpevent_make_send_failed(
*/
*/
memcpy
(
&
ssf
->
ssf_info
,
&
chunk
->
sinfo
,
sizeof
(
struct
sctp_sndrcvinfo
));
memcpy
(
&
ssf
->
ssf_info
,
&
chunk
->
sinfo
,
sizeof
(
struct
sctp_sndrcvinfo
));
/* Per TSVWG discussion with Randy. Allow the application to
* ressemble a fragmented message.
*/
ssf
->
ssf_info
.
sinfo_flags
=
chunk
->
chunk_hdr
->
flags
;
/* Socket Extensions for SCTP
/* Socket Extensions for SCTP
* 5.3.1.4 SCTP_SEND_FAILED
* 5.3.1.4 SCTP_SEND_FAILED
*
*
...
...
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