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
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)
}
/* 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
{
/* Chunks waiting to be submitted to lower layer. */
...
...
@@ -459,9 +459,13 @@ struct sctp_datamsg {
struct
list_head
track
;
/* Reference counting. */
atomic_t
refcnt
;
/* When is this message no longer interesting to the peer? */
unsigned
long
expires_at
;
/* Did the messenge fail to send? */
int
send_error
;
char
send_failed
;
/* Control whether fragments from this message can expire. */
char
can_expire
;
};
struct
sctp_datamsg
*
sctp_datamsg_from_user
(
struct
sctp_association
*
,
...
...
@@ -473,6 +477,9 @@ void sctp_datamsg_hold(struct sctp_datamsg *);
void
sctp_datamsg_free
(
struct
sctp_datamsg
*
);
void
sctp_datamsg_track
(
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
*
...
...
@@ -545,18 +552,6 @@ struct sctp_chunk {
/* We fill this in if we are calculating RTT. */
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? */
union
sctp_addr
source
;
/* Destination address for this chunk. */
...
...
@@ -570,6 +565,18 @@ struct sctp_chunk {
* go. It is NULL if we have no preference.
*/
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
*
);
...
...
@@ -580,10 +587,10 @@ struct sctp_chunk *sctp_make_chunk(const struct sctp_association *, __u8 type,
__u8
flags
,
int
size
);
void
sctp_chunk_free
(
struct
sctp_chunk
*
);
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
*
,
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
*
);
const
union
sctp_addr
*
sctp_source
(
const
struct
sctp_chunk
*
chunk
);
...
...
@@ -847,7 +854,7 @@ struct sctp_transport {
/* A flag which indicates the occurrence of a changeover */
char
changeover_active
;
/* A glag which indicates whether the change of primary is
* the first switch to this destination address during an
* active switch.
...
...
@@ -1024,7 +1031,7 @@ struct sctp_bind_addr {
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_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
,
sctp_scope_t
scope
,
int
gfp
,
int
flags
);
int
sctp_add_bind_addr
(
struct
sctp_bind_addr
*
,
union
sctp_addr
*
,
...
...
@@ -1613,7 +1620,7 @@ struct sctp_association {
/* Need to send an ECNE Chunk? */
char
need_ecne
;
/* Is it a temporary association? */
/* Is it a temporary association? */
char
temp
;
};
...
...
net/sctp/chunk.c
View file @
0c336e6d
...
...
@@ -55,8 +55,8 @@ void sctp_datamsg_init(struct sctp_datamsg *msg)
atomic_set
(
&
msg
->
refcnt
,
1
);
msg
->
send_failed
=
0
;
msg
->
send_error
=
0
;
msg
->
can_expire
=
0
;
INIT_LIST_HEAD
(
&
msg
->
chunks
);
INIT_LIST_HEAD
(
&
msg
->
track
);
}
/* Allocate and initialize datamsg. */
...
...
@@ -84,7 +84,7 @@ static void sctp_datamsg_destroy(struct sctp_datamsg *msg)
notify
=
msg
->
send_failed
?
-
1
:
0
;
/* Release all references. */
list_for_each_safe
(
pos
,
temp
,
&
msg
->
track
)
{
list_for_each_safe
(
pos
,
temp
,
&
msg
->
chunks
)
{
list_del
(
pos
);
chunk
=
list_entry
(
pos
,
struct
sctp_chunk
,
frag_list
);
/* Check whether we _really_ need to notify. */
...
...
@@ -94,7 +94,7 @@ static void sctp_datamsg_destroy(struct sctp_datamsg *msg)
error
=
msg
->
send_error
;
else
error
=
asoc
->
outqueue
.
error
;
sp
=
sctp_sk
(
asoc
->
base
.
sk
);
notify
=
sctp_ulpevent_type_enabled
(
SCTP_SEND_FAILED
,
&
sp
->
subscribe
);
...
...
@@ -107,8 +107,8 @@ static void sctp_datamsg_destroy(struct sctp_datamsg *msg)
sent
=
SCTP_DATA_SENT
;
else
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
);
if
(
ev
)
sctp_ulpq_tail_event
(
&
asoc
->
ulpq
,
ev
);
...
...
@@ -146,7 +146,6 @@ void sctp_datamsg_free(struct sctp_datamsg *msg)
void
sctp_datamsg_track
(
struct
sctp_chunk
*
chunk
)
{
sctp_chunk_hold
(
chunk
);
list_add_tail
(
&
chunk
->
frag_list
,
&
chunk
->
msg
->
track
);
}
/* Assign a chunk to this datamsg. */
...
...
@@ -179,6 +178,20 @@ struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *asoc,
if
(
!
msg
)
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? */
max
=
asoc
->
pmtu
;
if
(
max
<
SCTP_MIN_PMTU
)
...
...
@@ -191,7 +204,6 @@ struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *asoc,
/* Subtract out the overhead of a data chunk header. */
max
-=
sizeof
(
struct
sctp_data_chunk
);
whole
=
0
;
/* If user has specified smaller fragmentation, make it so. */
...
...
@@ -289,3 +301,27 @@ struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *asoc,
sctp_datamsg_free
(
msg
);
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)
if
(
sctp_chunk_is_data
(
chunk
))
{
if
(
!
chunk
->
has_tsn
)
{
sctp_chunk_assign_ssn
(
chunk
);
sctp_chunk_assign_tsn
(
chunk
);
/* 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,
rwnd
=
0
;
asoc
->
peer
.
rwnd
=
rwnd
;
/* Has been accepted for transmission. */
chunk
->
msg
->
can_expire
=
0
;
finish:
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,
*/
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
))
return
1
;
return
0
;
...
...
@@ -174,7 +174,7 @@ static inline int sctp_cacc_skip_3_2(struct sctp_transport *primary, __u32 tsn)
/*
* SFR-CACC algorithm:
* 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,
* then the sender MUST futher execute steps 3.1 and
* 3.2 to determine if the missing report count for
...
...
@@ -251,8 +251,7 @@ void sctp_outq_teardown(struct sctp_outq *q)
chunk
=
list_entry
(
lchunk
,
struct
sctp_chunk
,
transmitted_list
);
/* Mark as part of a failed message. */
chunk
->
msg
->
send_failed
=
1
;
/* Generate a SEND FAILED event. */
sctp_datamsg_fail
(
chunk
,
q
->
error
);
sctp_chunk_free
(
chunk
);
}
}
...
...
@@ -262,6 +261,7 @@ void sctp_outq_teardown(struct sctp_outq *q)
list_del
(
lchunk
);
chunk
=
list_entry
(
lchunk
,
struct
sctp_chunk
,
transmitted_list
);
sctp_datamsg_fail
(
chunk
,
q
->
error
);
sctp_chunk_free
(
chunk
);
}
...
...
@@ -270,6 +270,7 @@ void sctp_outq_teardown(struct sctp_outq *q)
list_del
(
lchunk
);
chunk
=
list_entry
(
lchunk
,
struct
sctp_chunk
,
transmitted_list
);
sctp_datamsg_fail
(
chunk
,
q
->
error
);
sctp_chunk_free
(
chunk
);
}
...
...
@@ -277,7 +278,7 @@ void sctp_outq_teardown(struct sctp_outq *q)
while
((
chunk
=
sctp_outq_dequeue_data
(
q
)))
{
/* Mark as send failure. */
chunk
->
msg
->
send_failed
=
1
;
sctp_datamsg_fail
(
chunk
,
q
->
error
)
;
sctp_chunk_free
(
chunk
);
}
...
...
@@ -800,27 +801,25 @@ int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout)
*/
if
(
chunk
->
sinfo
.
sinfo_stream
>=
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
);
continue
;
}
/* Now do delayed assignment of SSN. This will
* probably change again when we start supporting
* large (> approximately 2^16) size messages.
*/
sctp_chunk_assign_ssn
(
chunk
);
/* Has this chunk expired? */
if
(
sctp_datamsg_expires
(
chunk
))
{
sctp_datamsg_fail
(
chunk
,
0
);
sctp_chunk_free
(
chunk
);
continue
;
}
/* If there is a specified transport, use it.
* Otherwise, we want to use the active path.
*/
new_transport
=
chunk
->
transport
;
if
(
new_transport
==
NULL
||
!
new_transport
->
active
)
if
(
!
new_transport
||
!
new_transport
->
active
)
new_transport
=
asoc
->
peer
.
active_path
;
/* Change packets if necessary. */
...
...
@@ -1024,10 +1023,10 @@ int sctp_outq_sack(struct sctp_outq *q, struct sctp_sackhdr *sack)
/*
* 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.
*
* 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
* cleared. The CYCLING_CHANGEOVER flag SHOULD also be cleared for
* all destinations.
...
...
@@ -1041,7 +1040,7 @@ int sctp_outq_sack(struct sctp_outq *q, struct sctp_sackhdr *sack)
}
}
/*
/*
* SFR-CACC algorithm:
* 2) If the SACK contains gap acks and the flag CHANGEOVER_ACTIVE
* 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)
transport
,
sack
,
highest_new_tsn
);
/*
* 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.
*/
if
(
transport
->
cacc
.
cacc_saw_newack
)
...
...
@@ -1097,7 +1096,7 @@ int sctp_outq_sack(struct sctp_outq *q, struct sctp_sackhdr *sack)
list_for_each
(
pos
,
transport_list
)
{
transport
=
list_entry
(
pos
,
struct
sctp_transport
,
transports
);
sctp_mark_missing
(
q
,
&
transport
->
transmitted
,
transport
,
sctp_mark_missing
(
q
,
&
transport
->
transmitted
,
transport
,
highest_new_tsn
,
count_of_newacks
);
}
...
...
@@ -1275,8 +1274,8 @@ static void sctp_check_transmitted(struct sctp_outq *q,
* the destination that the TSN was
* sent to.
*/
if
(
transport
&&
sack
->
num_gap_ack_blocks
&&
if
(
transport
&&
sack
->
num_gap_ack_blocks
&&
q
->
asoc
->
peer
.
primary_path
->
cacc
.
changeover_active
)
transport
->
cacc
.
cacc_saw_newack
...
...
@@ -1529,12 +1528,12 @@ static void sctp_mark_missing(struct sctp_outq *q,
TSN_lt
(
tsn
,
highest_new_tsn_in_sack
))
{
/* SFR-CACC may require us to skip marking
* this chunk as missing.
* this chunk as missing.
*/
if
(
!
transport
||
!
sctp_cacc_skip
(
primary
,
transport
,
count_of_newacks
,
tsn
))
{
chunk
->
tsn_missing_report
++
;
SCTP_DEBUG_PRINTK
(
"%s: TSN 0x%x missing counter: %d
\n
"
,
__FUNCTION__
,
tsn
,
...
...
net/sctp/sm_make_chunk.c
View file @
0c336e6d
...
...
@@ -992,7 +992,7 @@ struct sctp_chunk *sctp_chunkify(struct sk_buff *skb,
retval
->
has_tsn
=
0
;
retval
->
has_ssn
=
0
;
retval
->
rtt_in_progress
=
0
;
retval
->
sent_at
=
jiffies
;
retval
->
sent_at
=
0
;
retval
->
singleton
=
1
;
retval
->
end_of_packet
=
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,
* 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
||
asoc
->
rwnd_over
||
(
datalen
>
asoc
->
rwnd
+
asoc
->
frag_point
))
{
/* If this is the next TSN, consider reneging to make
* 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,
long
timeo
;
__u16
sinfo_flags
=
0
;
struct
sctp_datamsg
*
datamsg
;
struct
list_head
*
pos
,
*
temp
;
struct
list_head
*
pos
;
int
msg_flags
=
msg
->
msg_flags
;
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,
}
/* 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
);
list_del_init
(
pos
);
sctp_datamsg_track
(
chunk
);
/* Do accounting for the write space. */
...
...
@@ -1143,7 +1142,11 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk,
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
);
/* Did the lower layer accept the chunk? */
if
(
err
)
...
...
@@ -1152,7 +1155,7 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk,
}
sctp_datamsg_free
(
datamsg
);
if
(
err
)
if
(
err
)
goto
out_free
;
else
err
=
msg_len
;
...
...
@@ -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()
* is called, set RCV_SHUTDOWN flag.
*/
*/
if
(
sctp_state
(
assoc
,
CLOSED
)
&&
sctp_style
(
newsk
,
TCP
))
newsk
->
shutdown
|=
RCV_SHUTDOWN
;
...
...
net/sctp/ulpevent.c
View file @
0c336e6d
...
...
@@ -425,6 +425,9 @@ struct sctp_ulpevent *sctp_ulpevent_make_send_failed(
struct
sctp_send_failed
*
ssf
;
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. */
skb
=
skb_copy_expand
(
chunk
->
skb
,
sizeof
(
struct
sctp_send_failed
),
/* headroom */
...
...
@@ -434,7 +437,8 @@ struct sctp_ulpevent *sctp_ulpevent_make_send_failed(
goto
fail
;
/* 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. */
event
=
sctp_skb2event
(
skb
);
...
...
@@ -475,7 +479,8 @@ struct sctp_ulpevent *sctp_ulpevent_make_send_failed(
* This field is the total length of the notification data, including
* 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
* 5.3.1.4 SCTP_SEND_FAILED
...
...
@@ -496,6 +501,11 @@ struct sctp_ulpevent *sctp_ulpevent_make_send_failed(
*/
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
* 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