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
c15987c4
Commit
c15987c4
authored
Jul 10, 2003
by
Sridhar Samudrala
Browse files
Options
Browse Files
Download
Plain Diff
Merge us.ibm.com:/home/sridhar/BK/linux-2.5.75
into us.ibm.com:/home/sridhar/BK/lksctp-2.5.75
parents
c3d5155c
691eb684
Changes
13
Show whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
185 additions
and
138 deletions
+185
-138
include/net/sctp/sm.h
include/net/sctp/sm.h
+2
-1
include/net/sctp/ulpevent.h
include/net/sctp/ulpevent.h
+3
-1
net/sctp/associola.c
net/sctp/associola.c
+1
-1
net/sctp/chunk.c
net/sctp/chunk.c
+2
-2
net/sctp/output.c
net/sctp/output.c
+25
-12
net/sctp/outqueue.c
net/sctp/outqueue.c
+6
-8
net/sctp/sm_make_chunk.c
net/sctp/sm_make_chunk.c
+7
-3
net/sctp/sm_sideeffect.c
net/sctp/sm_sideeffect.c
+1
-1
net/sctp/sm_statefuns.c
net/sctp/sm_statefuns.c
+2
-2
net/sctp/socket.c
net/sctp/socket.c
+15
-5
net/sctp/transport.c
net/sctp/transport.c
+1
-0
net/sctp/ulpevent.c
net/sctp/ulpevent.c
+116
-97
net/sctp/ulpqueue.c
net/sctp/ulpqueue.c
+4
-5
No files found.
include/net/sctp/sm.h
View file @
c15987c4
...
...
@@ -231,7 +231,8 @@ struct sctp_chunk *sctp_make_data_empty(struct sctp_association *,
struct
sctp_chunk
*
sctp_make_ecne
(
const
struct
sctp_association
*
,
const
__u32
);
struct
sctp_chunk
*
sctp_make_sack
(
const
struct
sctp_association
*
);
struct
sctp_chunk
*
sctp_make_shutdown
(
const
struct
sctp_association
*
asoc
);
struct
sctp_chunk
*
sctp_make_shutdown
(
const
struct
sctp_association
*
asoc
,
const
struct
sctp_chunk
*
chunk
);
struct
sctp_chunk
*
sctp_make_shutdown_ack
(
const
struct
sctp_association
*
asoc
,
const
struct
sctp_chunk
*
);
struct
sctp_chunk
*
sctp_make_shutdown_complete
(
const
struct
sctp_association
*
,
...
...
include/net/sctp/ulpevent.h
View file @
c15987c4
...
...
@@ -40,6 +40,7 @@
* Jon Grimm <jgrimm@us.ibm.com>
* La Monte H.P. Yarroll <piggy@acm.org>
* Karl Knutson <karl@athena.chicago.il.us>
* Sridhar Samudrala <sri@us.ibm.com>
*
* Any bugs reported given to us we will try to fix... any fixes shared will
* be incorporated into the next SCTP release.
...
...
@@ -72,9 +73,10 @@ static inline struct sctp_ulpevent *sctp_skb2event(struct sk_buff *skb)
}
struct
sctp_ulpevent
*
sctp_ulpevent_new
(
int
size
,
int
flags
,
int
gfp
);
struct
sctp_ulpevent
*
sctp_ulpevent_init
(
struct
sctp_ulpevent
*
,
int
flags
);
void
sctp_ulpevent_init
(
struct
sctp_ulpevent
*
,
int
flags
);
void
sctp_ulpevent_free
(
struct
sctp_ulpevent
*
);
int
sctp_ulpevent_is_notification
(
const
struct
sctp_ulpevent
*
);
void
sctp_queue_purge_ulpevents
(
struct
sk_buff_head
*
list
);
struct
sctp_ulpevent
*
sctp_ulpevent_make_assoc_change
(
const
struct
sctp_association
*
asoc
,
...
...
net/sctp/associola.c
View file @
c15987c4
...
...
@@ -877,7 +877,7 @@ void sctp_assoc_migrate(struct sctp_association *assoc, struct sock *newsk)
/* Delete the association from the old endpoint's list of
* associations.
*/
list_del
(
&
assoc
->
asocs
);
list_del
_init
(
&
assoc
->
asocs
);
/* Decrement the backlog value for a TCP-style socket. */
if
(
sctp_style
(
oldsk
,
TCP
))
...
...
net/sctp/chunk.c
View file @
c15987c4
...
...
@@ -85,7 +85,7 @@ static void sctp_datamsg_destroy(struct sctp_datamsg *msg)
/* Release all references. */
list_for_each_safe
(
pos
,
temp
,
&
msg
->
chunks
)
{
list_del
(
pos
);
list_del
_init
(
pos
);
chunk
=
list_entry
(
pos
,
struct
sctp_chunk
,
frag_list
);
/* Check whether we _really_ need to notify. */
if
(
notify
<
0
)
{
...
...
@@ -294,7 +294,7 @@ struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *asoc,
errout:
list_for_each_safe
(
pos
,
temp
,
&
msg
->
chunks
)
{
list_del
(
pos
);
list_del
_init
(
pos
);
chunk
=
list_entry
(
pos
,
struct
sctp_chunk
,
frag_list
);
sctp_chunk_free
(
chunk
);
}
...
...
net/sctp/output.c
View file @
c15987c4
...
...
@@ -97,6 +97,7 @@ struct sctp_packet *sctp_packet_init(struct sctp_packet *packet,
packet
->
source_port
=
sport
;
packet
->
destination_port
=
dport
;
skb_queue_head_init
(
&
packet
->
chunks
);
packet
->
size
=
SCTP_IP_OVERHEAD
;
packet
->
vtag
=
0
;
packet
->
ecn_capable
=
0
;
packet
->
get_prepend_chunk
=
NULL
;
...
...
@@ -219,9 +220,8 @@ sctp_xmit_t sctp_packet_append_chunk(struct sctp_packet *packet,
/* Both control chunks and data chunks with TSNs are
* non-fragmentable.
*/
if
(
packet_empty
)
{
/* We no longer do refragmentation at all.
if
(
packet_empty
||
!
sctp_chunk_is_data
(
chunk
))
{
/* We no longer do re-fragmentation.
* Just fragment at the IP layer, if we
* actually hit this condition
*/
...
...
@@ -229,7 +229,7 @@ sctp_xmit_t sctp_packet_append_chunk(struct sctp_packet *packet,
packet
->
ipfragok
=
1
;
goto
append
;
}
else
{
/* !packet_empty */
}
else
{
retval
=
SCTP_XMIT_PMTU_FULL
;
goto
finish
;
}
...
...
@@ -283,20 +283,18 @@ int sctp_packet_transmit(struct sctp_packet *packet)
__u8
has_data
=
0
;
struct
dst_entry
*
dst
;
/* Do NOT generate a chunkless packet... */
if
(
skb_queue_empty
(
&
packet
->
chunks
))
/* Do NOT generate a chunkless packet. */
chunk
=
(
struct
sctp_chunk
*
)
skb_peek
(
&
packet
->
chunks
);
if
(
unlikely
(
!
chunk
))
return
err
;
/* Set up convenience variables... */
chunk
=
(
struct
sctp_chunk
*
)
(
packet
->
chunks
.
next
);
sk
=
chunk
->
skb
->
sk
;
/* Allocate the new skb. */
nskb
=
dev_alloc_skb
(
packet
->
size
);
if
(
!
nskb
)
{
err
=
-
ENOMEM
;
goto
out
;
}
if
(
!
nskb
)
goto
nomem
;
/* Make sure the outbound skb has enough header room reserved. */
skb_reserve
(
nskb
,
SCTP_IP_OVERHEAD
);
...
...
@@ -468,9 +466,11 @@ int sctp_packet_transmit(struct sctp_packet *packet)
if
(
!
nskb
->
dst
)
goto
no_route
;
SCTP_DEBUG_PRINTK
(
"***sctp_transmit_packet*** skb len
gth
%d
\n
"
,
SCTP_DEBUG_PRINTK
(
"***sctp_transmit_packet*** skb len %d
\n
"
,
nskb
->
len
);
(
*
tp
->
af_specific
->
sctp_xmit
)(
nskb
,
tp
,
packet
->
ipfragok
);
out:
packet
->
size
=
SCTP_IP_OVERHEAD
;
return
err
;
...
...
@@ -486,7 +486,20 @@ int sctp_packet_transmit(struct sctp_packet *packet)
* required.
*/
/* err = -EHOSTUNREACH; */
err:
/* Control chunks are unreliable so just drop them. DATA chunks
* will get resent or dropped later.
*/
while
((
chunk
=
(
struct
sctp_chunk
*
)
__skb_dequeue
(
&
packet
->
chunks
)))
{
if
(
!
sctp_chunk_is_data
(
chunk
))
sctp_chunk_free
(
chunk
);
}
goto
out
;
nomem:
err
=
-
ENOMEM
;
printk
(
"%s alloc_skb failed.
\n
"
,
__FUNCTION__
);
goto
err
;
}
/********************************************************************
...
...
net/sctp/outqueue.c
View file @
c15987c4
...
...
@@ -258,7 +258,7 @@ void sctp_outq_teardown(struct sctp_outq *q)
/* Throw away chunks that have been gap ACKed. */
list_for_each_safe
(
lchunk
,
temp
,
&
q
->
sacked
)
{
list_del
(
lchunk
);
list_del
_init
(
lchunk
);
chunk
=
list_entry
(
lchunk
,
struct
sctp_chunk
,
transmitted_list
);
sctp_datamsg_fail
(
chunk
,
q
->
error
);
...
...
@@ -267,7 +267,7 @@ void sctp_outq_teardown(struct sctp_outq *q)
/* Throw away any chunks in the retransmit queue. */
list_for_each_safe
(
lchunk
,
temp
,
&
q
->
retransmit
)
{
list_del
(
lchunk
);
list_del
_init
(
lchunk
);
chunk
=
list_entry
(
lchunk
,
struct
sctp_chunk
,
transmitted_list
);
sctp_datamsg_fail
(
chunk
,
q
->
error
);
...
...
@@ -445,7 +445,7 @@ void sctp_retransmit_mark(struct sctp_outq *q,
/* Move the chunk to the retransmit queue. The chunks
* on the retransmit queue is always kept in order.
*/
list_del
(
lchunk
);
list_del
_init
(
lchunk
);
sctp_retransmit_insert
(
lchunk
,
q
);
}
}
...
...
@@ -1007,7 +1007,7 @@ int sctp_outq_sack(struct sctp_outq *q, struct sctp_sackhdr *sack)
struct
sctp_association
*
asoc
=
q
->
asoc
;
struct
sctp_transport
*
transport
;
struct
sctp_chunk
*
tchunk
;
struct
list_head
*
lchunk
,
*
transport_list
,
*
pos
;
struct
list_head
*
lchunk
,
*
transport_list
,
*
pos
,
*
temp
;
sctp_sack_variable_t
*
frags
=
sack
->
variable
;
__u32
sack_ctsn
,
ctsn
,
tsn
;
__u32
highest_tsn
,
highest_new_tsn
;
...
...
@@ -1115,15 +1115,13 @@ int sctp_outq_sack(struct sctp_outq *q, struct sctp_sackhdr *sack)
"%p is 0x%x.
\n
"
,
__FUNCTION__
,
asoc
,
ctsn
);
/* Throw away stuff rotting on the sack queue. */
list_for_each
(
lchunk
,
&
q
->
sacked
)
{
list_for_each
_safe
(
lchunk
,
temp
,
&
q
->
sacked
)
{
tchunk
=
list_entry
(
lchunk
,
struct
sctp_chunk
,
transmitted_list
);
tsn
=
ntohl
(
tchunk
->
subh
.
data_hdr
->
tsn
);
if
(
TSN_lte
(
tsn
,
ctsn
))
{
lchunk
=
lchunk
->
prev
;
if
(
TSN_lte
(
tsn
,
ctsn
))
sctp_chunk_free
(
tchunk
);
}
}
/* ii) Set rwnd equal to the newly received a_rwnd minus the
* number of bytes still outstanding after processing the
...
...
net/sctp/sm_make_chunk.c
View file @
c15987c4
...
...
@@ -667,7 +667,8 @@ struct sctp_chunk *sctp_make_sack(const struct sctp_association *asoc)
}
/* Make a SHUTDOWN chunk. */
struct
sctp_chunk
*
sctp_make_shutdown
(
const
struct
sctp_association
*
asoc
)
struct
sctp_chunk
*
sctp_make_shutdown
(
const
struct
sctp_association
*
asoc
,
const
struct
sctp_chunk
*
chunk
)
{
struct
sctp_chunk
*
retval
;
sctp_shutdownhdr_t
shut
;
...
...
@@ -683,6 +684,9 @@ struct sctp_chunk *sctp_make_shutdown(const struct sctp_association *asoc)
retval
->
subh
.
shutdown_hdr
=
sctp_addto_chunk
(
retval
,
sizeof
(
shut
),
&
shut
);
if
(
chunk
)
retval
->
transport
=
chunk
->
transport
;
nodata:
return
retval
;
}
...
...
@@ -1089,7 +1093,7 @@ void sctp_chunk_free(struct sctp_chunk *chunk)
{
/* Make sure that we are not on any list. */
skb_unlink
((
struct
sk_buff
*
)
chunk
);
list_del
(
&
chunk
->
transmitted_list
);
list_del
_init
(
&
chunk
->
transmitted_list
);
/* Release our reference on the message tracker. */
if
(
chunk
->
msg
)
...
...
@@ -1850,7 +1854,7 @@ int sctp_process_init(struct sctp_association *asoc, sctp_cid_t cid,
/* Release the transport structures. */
list_for_each_safe
(
pos
,
temp
,
&
asoc
->
peer
.
transport_addr_list
)
{
transport
=
list_entry
(
pos
,
struct
sctp_transport
,
transports
);
list_del
(
pos
);
list_del
_init
(
pos
);
sctp_transport_free
(
transport
);
}
nomem:
...
...
net/sctp/sm_sideeffect.c
View file @
c15987c4
...
...
@@ -962,7 +962,7 @@ int sctp_cmd_interpreter(sctp_event_t event_type, sctp_subtype_t subtype,
asoc
->
overall_error_count
=
0
;
/* Generate a SHUTDOWN chunk. */
new_obj
=
sctp_make_shutdown
(
asoc
);
new_obj
=
sctp_make_shutdown
(
asoc
,
chunk
);
if
(
!
new_obj
)
goto
nomem
;
sctp_add_cmd_sf
(
commands
,
SCTP_CMD_REPLY
,
...
...
net/sctp/sm_statefuns.c
View file @
c15987c4
...
...
@@ -3862,7 +3862,7 @@ sctp_disposition_t sctp_sf_do_9_2_start_shutdown(
* in the Cumulative TSN Ack field the last sequential TSN it
* has received from the peer.
*/
reply
=
sctp_make_shutdown
(
asoc
);
reply
=
sctp_make_shutdown
(
asoc
,
NULL
);
if
(
!
reply
)
goto
nomem
;
...
...
@@ -4179,7 +4179,7 @@ sctp_disposition_t sctp_sf_t2_timer_expire(const struct sctp_endpoint *ep,
switch
(
asoc
->
state
)
{
case
SCTP_STATE_SHUTDOWN_SENT
:
reply
=
sctp_make_shutdown
(
asoc
);
reply
=
sctp_make_shutdown
(
asoc
,
NULL
);
break
;
case
SCTP_STATE_SHUTDOWN_ACK_SENT
:
...
...
net/sctp/socket.c
View file @
c15987c4
...
...
@@ -768,8 +768,8 @@ SCTP_STATIC void sctp_close(struct sock *sk, long timeout)
}
/* Clean up any skbs sitting on the receive queue. */
s
kb_queue_purge
(
&
sk
->
sk_receive_queue
);
s
kb_queue_purge
(
&
sctp_sk
(
sk
)
->
pd_lobby
);
s
ctp_queue_purge_ulpevents
(
&
sk
->
sk_receive_queue
);
s
ctp_queue_purge_ulpevents
(
&
sctp_sk
(
sk
)
->
pd_lobby
);
/* On a TCP-style socket, block for at most linger_time if set. */
if
(
sctp_style
(
sk
,
TCP
)
&&
timeout
)
...
...
@@ -1342,8 +1342,7 @@ SCTP_STATIC int sctp_recvmsg(struct kiocb *iocb, struct sock *sk,
/* When only partial message is copied to the user, increase
* rwnd by that amount. If all the data in the skb is read,
* rwnd is updated when the skb's destructor is called via
* sctp_ulpevent_free().
* rwnd is updated when the event is freed.
*/
sctp_assoc_rwnd_increase
(
event
->
asoc
,
copied
);
goto
out
;
...
...
@@ -1354,7 +1353,18 @@ SCTP_STATIC int sctp_recvmsg(struct kiocb *iocb, struct sock *sk,
msg
->
msg_flags
&=
~
MSG_EOR
;
out_free:
sctp_ulpevent_free
(
event
);
/* Free the skb. */
if
(
flags
&
MSG_PEEK
)
{
/* Release the skb reference acquired after peeking the skb in
* sctp_skb_recv_datagram().
*/
kfree_skb
(
skb
);
}
else
{
/* Free the event which includes releasing the reference to
* the owner of the skb, freeing the skb and updating the
* rwnd.
*/
sctp_ulpevent_free
(
event
);
}
out:
sctp_release_sock
(
sk
);
return
err
;
...
...
net/sctp/transport.c
View file @
c15987c4
...
...
@@ -117,6 +117,7 @@ struct sctp_transport *sctp_transport_init(struct sctp_transport *peer,
INIT_LIST_HEAD
(
&
peer
->
transmitted
);
INIT_LIST_HEAD
(
&
peer
->
send_ready
);
INIT_LIST_HEAD
(
&
peer
->
transports
);
sctp_packet_init
(
&
peer
->
packet
,
peer
,
0
,
0
);
/* Set up the retransmission timer. */
init_timer
(
&
peer
->
T3_rtx_timer
);
...
...
net/sctp/ulpevent.c
View file @
c15987c4
...
...
@@ -35,6 +35,7 @@
* Written or modified by:
* Jon Grimm <jgrimm@us.ibm.com>
* La Monte H.P. Yarroll <piggy@acm.org>
* Sridhar Samudrala <sri@us.ibm.com>
*
* Any bugs reported given to us we will try to fix... any fixes shared will
* be incorporated into the next SCTP release.
...
...
@@ -46,10 +47,12 @@
#include <net/sctp/sctp.h>
#include <net/sctp/sm.h>
static
void
sctp_ulpevent_set_owner_r
(
struct
sk_buff
*
skb
,
struct
sctp_association
*
asoc
);
static
void
sctp_ulpevent_set_owner
(
struct
sk_buff
*
skb
,
static
inline
void
sctp_ulpevent_set_owner
(
struct
sctp_ulpevent
*
event
,
const
struct
sctp_association
*
asoc
);
static
inline
void
sctp_ulpevent_release_owner
(
struct
sctp_ulpevent
*
event
);
static
void
sctp_ulpevent_receive_data
(
struct
sctp_ulpevent
*
event
,
struct
sctp_association
*
asoc
);
static
void
sctp_ulpevent_release_data
(
struct
sctp_ulpevent
*
event
);
/* Create a new sctp_ulpevent. */
struct
sctp_ulpevent
*
sctp_ulpevent_new
(
int
size
,
int
msg_flags
,
int
gfp
)
...
...
@@ -62,30 +65,19 @@ struct sctp_ulpevent *sctp_ulpevent_new(int size, int msg_flags, int gfp)
goto
fail
;
event
=
sctp_skb2event
(
skb
);
event
=
sctp_ulpevent_init
(
event
,
msg_flags
);
if
(
!
event
)
goto
fail_init
;
sctp_ulpevent_init
(
event
,
msg_flags
);
return
event
;
fail_init:
kfree_skb
(
skb
);
fail:
return
NULL
;
}
/* Initialize an ULP event from an given skb. */
struct
sctp_ulpevent
*
sctp_ulpevent_init
(
struct
sctp_ulpevent
*
event
,
int
msg_flags
)
void
sctp_ulpevent_init
(
struct
sctp_ulpevent
*
event
,
int
msg_flags
)
{
memset
(
event
,
sizeof
(
struct
sctp_ulpevent
),
0x00
);
event
->
msg_flags
=
msg_flags
;
return
event
;
}
/* Dispose of an event. */
void
sctp_ulpevent_free
(
struct
sctp_ulpevent
*
event
)
{
kfree_skb
(
sctp_event2skb
(
event
));
}
/* Is this a MSG_NOTIFICATION? */
...
...
@@ -189,7 +181,7 @@ struct sctp_ulpevent *sctp_ulpevent_make_assoc_change(
* All notifications for a given association have the same association
* identifier. For TCP style socket, this field is ignored.
*/
sctp_ulpevent_set_owner
(
skb
,
asoc
);
sctp_ulpevent_set_owner
(
event
,
asoc
);
sac
->
sac_assoc_id
=
sctp_assoc2id
(
asoc
);
return
event
;
...
...
@@ -281,7 +273,7 @@ struct sctp_ulpevent *sctp_ulpevent_make_peer_addr_change(
* All notifications for a given association have the same association
* identifier. For TCP style socket, this field is ignored.
*/
sctp_ulpevent_set_owner
(
skb
,
asoc
);
sctp_ulpevent_set_owner
(
event
,
asoc
);
spc
->
spc_assoc_id
=
sctp_assoc2id
(
asoc
);
/* Sockets API Extensions for SCTP
...
...
@@ -346,10 +338,7 @@ struct sctp_ulpevent *sctp_ulpevent_make_remote_error(
/* Embed the event fields inside the cloned skb. */
event
=
sctp_skb2event
(
skb
);
event
=
sctp_ulpevent_init
(
event
,
MSG_NOTIFICATION
);
if
(
!
event
)
goto
fail
;
sctp_ulpevent_init
(
event
,
MSG_NOTIFICATION
);
sre
=
(
struct
sctp_remote_error
*
)
skb_push
(
skb
,
sizeof
(
struct
sctp_remote_error
));
...
...
@@ -402,8 +391,7 @@ struct sctp_ulpevent *sctp_ulpevent_make_remote_error(
* All notifications for a given association have the same association
* identifier. For TCP style socket, this field is ignored.
*/
skb
=
sctp_event2skb
(
event
);
sctp_ulpevent_set_owner
(
skb
,
asoc
);
sctp_ulpevent_set_owner
(
event
,
asoc
);
sre
->
sre_assoc_id
=
sctp_assoc2id
(
asoc
);
return
event
;
...
...
@@ -442,9 +430,7 @@ struct sctp_ulpevent *sctp_ulpevent_make_send_failed(
/* Embed the event fields inside the cloned skb. */
event
=
sctp_skb2event
(
skb
);
event
=
sctp_ulpevent_init
(
event
,
MSG_NOTIFICATION
);
if
(
!
event
)
goto
fail
;
sctp_ulpevent_init
(
event
,
MSG_NOTIFICATION
);
ssf
=
(
struct
sctp_send_failed
*
)
skb_push
(
skb
,
sizeof
(
struct
sctp_send_failed
));
...
...
@@ -515,8 +501,7 @@ struct sctp_ulpevent *sctp_ulpevent_make_send_failed(
* same association identifier. For TCP style socket, this field is
* ignored.
*/
skb
=
sctp_event2skb
(
event
);
sctp_ulpevent_set_owner
(
skb
,
asoc
);
sctp_ulpevent_set_owner
(
event
,
asoc
);
ssf
->
ssf_assoc_id
=
sctp_assoc2id
(
asoc
);
return
event
;
...
...
@@ -579,7 +564,7 @@ struct sctp_ulpevent *sctp_ulpevent_make_shutdown_event(
* All notifications for a given association have the same association
* identifier. For TCP style socket, this field is ignored.
*/
sctp_ulpevent_set_owner
(
skb
,
asoc
);
sctp_ulpevent_set_owner
(
event
,
asoc
);
sse
->
sse_assoc_id
=
sctp_assoc2id
(
asoc
);
return
event
;
...
...
@@ -601,7 +586,7 @@ struct sctp_ulpevent *sctp_ulpevent_make_rcvmsg(struct sctp_association *asoc,
{
struct
sctp_ulpevent
*
event
;
struct
sctp_sndrcvinfo
*
info
;
struct
sk_buff
*
skb
,
*
list
;
struct
sk_buff
*
skb
;
size_t
padding
,
len
;
/* Clone the original skb, sharing the data. */
...
...
@@ -627,24 +612,15 @@ struct sctp_ulpevent *sctp_ulpevent_make_rcvmsg(struct sctp_association *asoc,
/* Fixup cloned skb with just this chunks data. */
skb_trim
(
skb
,
chunk
->
chunk_end
-
padding
-
skb
->
data
);
/* Set up a destructor to do rwnd accounting. */
sctp_ulpevent_set_owner_r
(
skb
,
asoc
);
/* Embed the event fields inside the cloned skb. */
event
=
sctp_skb2event
(
skb
);
/* Initialize event with flags 0. */
event
=
sctp_ulpevent_init
(
event
,
0
);
if
(
!
event
)
goto
fail_init
;
sctp_ulpevent_init
(
event
,
0
);
event
->
iif
=
sctp_chunk_iif
(
chunk
);
/* Note: Not clearing the entire event struct as
* this is just a fragment of the real event. However,
* we still need to do rwnd accounting.
*/
for
(
list
=
skb_shinfo
(
skb
)
->
frag_list
;
list
;
list
=
list
->
next
)
sctp_ulpevent_set_owner_r
(
list
,
asoc
);
sctp_ulpevent_receive_data
(
event
,
asoc
);
info
=
(
struct
sctp_sndrcvinfo
*
)
&
event
->
sndrcvinfo
;
...
...
@@ -735,9 +711,6 @@ struct sctp_ulpevent *sctp_ulpevent_make_rcvmsg(struct sctp_association *asoc,
return
event
;
fail_init:
kfree_skb
(
skb
);
fail:
return
NULL
;
}
...
...
@@ -793,6 +766,7 @@ struct sctp_ulpevent *sctp_ulpevent_make_pdapi(
*
* The association id field, holds the identifier for the association.
*/
sctp_ulpevent_set_owner
(
event
,
asoc
);
pd
->
pdapi_assoc_id
=
sctp_assoc2id
(
asoc
);
return
event
;
...
...
@@ -824,69 +798,114 @@ void sctp_ulpevent_read_sndrcvinfo(const struct sctp_ulpevent *event,
}
}
/*
Do accounting for bytes just read by use
r. */
static
void
sctp_
rcvmsg
_rfree
(
struct
sk_buff
*
skb
)
/*
Stub skb destructo
r. */
static
void
sctp_
stub
_rfree
(
struct
sk_buff
*
skb
)
{
struct
sctp_association
*
asoc
;
struct
sctp_ulpevent
*
event
;
/* Current stack structures assume that the rcv buffer is
* per socket. For UDP style sockets this is not true as
* multiple associations may be on a single UDP-style socket.
* Use the local private area of the skb to track the owning
* association.
/* WARNING: This function is just a warning not to use the
* skb destructor. If the skb is shared, we may get the destructor
* callback on some processor that does not own the sock_lock. This
* was occuring with PACKET socket applications that were monitoring
* our skbs. We can't take the sock_lock, because we can't risk
* recursing if we do really own the sock lock. Instead, do all
* of our rwnd manipulation while we own the sock_lock outright.
*/
event
=
sctp_skb2event
(
skb
);
asoc
=
event
->
asoc
;
sctp_assoc_rwnd_increase
(
asoc
,
skb_headlen
(
skb
));
sctp_association_put
(
asoc
);
}
/* Charge receive window for bytes received. */
static
void
sctp_ulpevent_set_owner_r
(
struct
sk_buff
*
skb
,
struct
sctp_association
*
asoc
)
/* Hold the association in case the msg_name needs read out of
* the association.
*/
static
inline
void
sctp_ulpevent_set_owner
(
struct
sctp_ulpevent
*
event
,
const
struct
sctp_association
*
asoc
)
{
struct
s
ctp_ulpevent
*
event
;
struct
s
k_buff
*
skb
;
/* The current stack structures assume that the rcv buffer is
* per socket. For UDP-style sockets this is not true as
* multiple associations may be on a single UDP-style socket.
* We use the local private area of the skb to track the owning
* association.
/* Cast away the const, as we are just wanting to
* bump the reference count.
*/
sctp_association_hold
(
asoc
);
sctp_association_hold
((
struct
sctp_association
*
)
asoc
);
skb
=
sctp_event2skb
(
event
);
skb
->
sk
=
asoc
->
base
.
sk
;
event
=
sctp_skb2event
(
skb
);
event
->
asoc
=
asoc
;
skb
->
destructor
=
sctp_rcvmsg_rfree
;
sctp_assoc_rwnd_decrease
(
asoc
,
skb_headlen
(
skb
));
event
->
asoc
=
(
struct
sctp_association
*
)
asoc
;
skb
->
destructor
=
sctp_stub_rfree
;
}
/* A simple destructor to give up the reference to the association. */
static
void
sctp_ulpevent_rfree
(
struct
sk_buff
*
skb
)
static
inline
void
sctp_ulpevent_release_owner
(
struct
sctp_ulpevent
*
event
)
{
struct
sctp_ulpevent
*
event
;
event
=
sctp_skb2event
(
skb
);
sctp_association_put
(
event
->
asoc
);
}
/* Hold the association in case the msg_name needs read out of
/* Do accounting for bytes received and hold a reference to the association
* for each skb.
*/
static
void
sctp_ulpevent_receive_data
(
struct
sctp_ulpevent
*
event
,
struct
sctp_association
*
asoc
)
{
struct
sk_buff
*
skb
,
*
frag
;
skb
=
sctp_event2skb
(
event
);
/* Set the owner and charge rwnd for bytes received. */
sctp_ulpevent_set_owner
(
event
,
asoc
);
sctp_assoc_rwnd_decrease
(
asoc
,
skb_headlen
(
skb
));
/* Note: Not clearing the entire event struct as this is just a
* fragment of the real event. However, we still need to do rwnd
* accounting.
* In general, the skb passed from IP can have only 1 level of
* fragments. But we allow multiple levels of fragments.
*/
for
(
frag
=
skb_shinfo
(
skb
)
->
frag_list
;
frag
;
frag
=
frag
->
next
)
{
sctp_ulpevent_receive_data
(
sctp_skb2event
(
frag
),
asoc
);
}
}
/* Do accounting for bytes just read by user and release the references to
* the association.
*/
static
void
sctp_ulpevent_set_owner
(
struct
sk_buff
*
skb
,
const
struct
sctp_association
*
asoc
)
static
void
sctp_ulpevent_release_data
(
struct
sctp_ulpevent
*
event
)
{
struct
s
ctp_ulpevent
*
event
;
struct
s
k_buff
*
skb
,
*
frag
;
/* Cast away the const, as we are just wanting to
* bump the reference count.
/* Current stack structures assume that the rcv buffer is
* per socket. For UDP style sockets this is not true as
* multiple associations may be on a single UDP-style socket.
* Use the local private area of the skb to track the owning
* association.
*/
sctp_association_hold
((
struct
sctp_association
*
)
asoc
);
skb
->
sk
=
asoc
->
base
.
sk
;
event
=
sctp_skb2event
(
skb
);
event
->
asoc
=
(
struct
sctp_association
*
)
asoc
;
skb
->
destructor
=
sctp_ulpevent_rfree
;
skb
=
sctp_event2skb
(
event
);
sctp_assoc_rwnd_increase
(
event
->
asoc
,
skb_headlen
(
skb
));
/* Don't forget the fragments. */
for
(
frag
=
skb_shinfo
(
skb
)
->
frag_list
;
frag
;
frag
=
frag
->
next
)
{
/* NOTE: skb_shinfos are recursive. Although IP returns
* skb's with only 1 level of fragments, SCTP reassembly can
* increase the levels.
*/
sctp_ulpevent_release_data
(
sctp_skb2event
(
frag
));
}
sctp_ulpevent_release_owner
(
event
);
}
/* Free a ulpevent that has an owner. It includes releasing the reference
* to the owner, updating the rwnd in case of a DATA event and freeing the
* skb.
* See comments in sctp_stub_rfree().
*/
void
sctp_ulpevent_free
(
struct
sctp_ulpevent
*
event
)
{
if
(
sctp_ulpevent_is_notification
(
event
))
sctp_ulpevent_release_owner
(
event
);
else
sctp_ulpevent_release_data
(
event
);
kfree_skb
(
sctp_event2skb
(
event
));
}
/* Purge the skb lists holding ulpevents. */
void
sctp_queue_purge_ulpevents
(
struct
sk_buff_head
*
list
)
{
struct
sk_buff
*
skb
;
while
((
skb
=
skb_dequeue
(
list
))
!=
NULL
)
sctp_ulpevent_free
(
sctp_skb2event
(
skb
));
}
net/sctp/ulpqueue.c
View file @
c15987c4
...
...
@@ -235,9 +235,9 @@ int sctp_ulpq_tail_event(struct sctp_ulpq *ulpq, struct sctp_ulpevent *event)
out_free:
if
(
sctp_event2skb
(
event
)
->
list
)
s
kb_queue_purge
(
sctp_event2skb
(
event
)
->
list
);
s
ctp_queue_purge_ulpevents
(
sctp_event2skb
(
event
)
->
list
);
else
kfree_skb
(
sctp_event2skb
(
event
)
);
sctp_ulpevent_free
(
event
);
return
0
;
}
...
...
@@ -289,7 +289,7 @@ static inline void sctp_ulpq_store_reasm(struct sctp_ulpq *ulpq,
* payload was fragmented on the way and ip had to reassemble them.
* We add the rest of skb's to the first skb's fraglist.
*/
static
inline
struct
sctp_ulpevent
*
sctp_make_reassembled_event
(
struct
sk_buff
*
f_frag
,
struct
sk_buff
*
l_frag
)
static
struct
sctp_ulpevent
*
sctp_make_reassembled_event
(
struct
sk_buff
*
f_frag
,
struct
sk_buff
*
l_frag
)
{
struct
sk_buff
*
pos
;
struct
sctp_ulpevent
*
event
;
...
...
@@ -329,7 +329,6 @@ static inline struct sctp_ulpevent *sctp_make_reassembled_event(struct sk_buff *
/* Break if we have reached the last fragment. */
if
(
pos
==
l_frag
)
break
;
pos
->
next
=
pnext
;
pos
=
pnext
;
};
...
...
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