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
78398488
Commit
78398488
authored
Jul 14, 2003
by
Sridhar Samudrala
Browse files
Options
Browse Files
Download
Plain Diff
Merge us.ibm.com:/home/sridhar/BK/linux-2.6.0-test1
into us.ibm.com:/home/sridhar/BK/lksctp-2.5.75
parents
8916e8f1
c15987c4
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 @
78398488
...
...
@@ -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 @
78398488
...
...
@@ -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 @
78398488
...
...
@@ -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 @
78398488
...
...
@@ -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 @
78398488
...
...
@@ -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 @
78398488
...
...
@@ -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 @
78398488
...
...
@@ -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 @
78398488
...
...
@@ -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 @
78398488
...
...
@@ -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 @
78398488
...
...
@@ -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 @
78398488
...
...
@@ -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 @
78398488
...
...
@@ -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 @
78398488
...
...
@@ -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