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
6c1b6c6b
Commit
6c1b6c6b
authored
Nov 15, 2010
by
David S. Miller
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'dccp' of
git://eden-feed.erg.abdn.ac.uk/net-next-2.6
parents
fe822240
7e87fe84
Changes
8
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
339 additions
and
343 deletions
+339
-343
include/linux/dccp.h
include/linux/dccp.h
+2
-0
net/dccp/ackvec.c
net/dccp/ackvec.c
+216
-201
net/dccp/ackvec.h
net/dccp/ackvec.h
+24
-14
net/dccp/ccids/ccid2.c
net/dccp/ccids/ccid2.c
+41
-93
net/dccp/ccids/ccid2.h
net/dccp/ccids/ccid2.h
+2
-0
net/dccp/input.c
net/dccp/input.c
+9
-22
net/dccp/options.c
net/dccp/options.c
+30
-13
net/dccp/output.c
net/dccp/output.c
+15
-0
No files found.
include/linux/dccp.h
View file @
6c1b6c6b
...
@@ -462,6 +462,7 @@ struct dccp_ackvec;
...
@@ -462,6 +462,7 @@ struct dccp_ackvec;
* @dccps_hc_rx_insert_options - receiver wants to add options when acking
* @dccps_hc_rx_insert_options - receiver wants to add options when acking
* @dccps_hc_tx_insert_options - sender wants to add options when sending
* @dccps_hc_tx_insert_options - sender wants to add options when sending
* @dccps_server_timewait - server holds timewait state on close (RFC 4340, 8.3)
* @dccps_server_timewait - server holds timewait state on close (RFC 4340, 8.3)
* @dccps_sync_scheduled - flag which signals "send out-of-band message soon"
* @dccps_xmitlet - tasklet scheduled by the TX CCID to dequeue data packets
* @dccps_xmitlet - tasklet scheduled by the TX CCID to dequeue data packets
* @dccps_xmit_timer - used by the TX CCID to delay sending (rate-based pacing)
* @dccps_xmit_timer - used by the TX CCID to delay sending (rate-based pacing)
* @dccps_syn_rtt - RTT sample from Request/Response exchange (in usecs)
* @dccps_syn_rtt - RTT sample from Request/Response exchange (in usecs)
...
@@ -503,6 +504,7 @@ struct dccp_sock {
...
@@ -503,6 +504,7 @@ struct dccp_sock {
__u8
dccps_hc_rx_insert_options
:
1
;
__u8
dccps_hc_rx_insert_options
:
1
;
__u8
dccps_hc_tx_insert_options
:
1
;
__u8
dccps_hc_tx_insert_options
:
1
;
__u8
dccps_server_timewait
:
1
;
__u8
dccps_server_timewait
:
1
;
__u8
dccps_sync_scheduled
:
1
;
struct
tasklet_struct
dccps_xmitlet
;
struct
tasklet_struct
dccps_xmitlet
;
struct
timer_list
dccps_xmit_timer
;
struct
timer_list
dccps_xmit_timer
;
};
};
...
...
net/dccp/ackvec.c
View file @
6c1b6c6b
This diff is collapsed.
Click to expand it.
net/dccp/ackvec.h
View file @
6c1b6c6b
...
@@ -29,6 +29,9 @@
...
@@ -29,6 +29,9 @@
/* Estimated minimum average Ack Vector length - used for updating MPS */
/* Estimated minimum average Ack Vector length - used for updating MPS */
#define DCCPAV_MIN_OPTLEN 16
#define DCCPAV_MIN_OPTLEN 16
/* Threshold for coping with large bursts of losses */
#define DCCPAV_BURST_THRESH (DCCPAV_MAX_ACKVEC_LEN / 8)
enum
dccp_ackvec_states
{
enum
dccp_ackvec_states
{
DCCPAV_RECEIVED
=
0x00
,
DCCPAV_RECEIVED
=
0x00
,
DCCPAV_ECN_MARKED
=
0x40
,
DCCPAV_ECN_MARKED
=
0x40
,
...
@@ -61,7 +64,6 @@ static inline u8 dccp_ackvec_state(const u8 *cell)
...
@@ -61,7 +64,6 @@ static inline u8 dccp_ackvec_state(const u8 *cell)
* %DCCP_SINGLE_OPT_MAXLEN cells in the live portion of @av_buf
* %DCCP_SINGLE_OPT_MAXLEN cells in the live portion of @av_buf
* @av_overflow: if 1 then buf_head == buf_tail indicates buffer wraparound
* @av_overflow: if 1 then buf_head == buf_tail indicates buffer wraparound
* @av_records: list of %dccp_ackvec_record (Ack Vectors sent previously)
* @av_records: list of %dccp_ackvec_record (Ack Vectors sent previously)
* @av_veclen: length of the live portion of @av_buf
*/
*/
struct
dccp_ackvec
{
struct
dccp_ackvec
{
u8
av_buf
[
DCCPAV_MAX_ACKVEC_LEN
];
u8
av_buf
[
DCCPAV_MAX_ACKVEC_LEN
];
...
@@ -72,7 +74,6 @@ struct dccp_ackvec {
...
@@ -72,7 +74,6 @@ struct dccp_ackvec {
bool
av_buf_nonce
[
DCCPAV_NUM_ACKVECS
];
bool
av_buf_nonce
[
DCCPAV_NUM_ACKVECS
];
u8
av_overflow
:
1
;
u8
av_overflow
:
1
;
struct
list_head
av_records
;
struct
list_head
av_records
;
u16
av_vec_len
;
};
};
/** struct dccp_ackvec_record - Records information about sent Ack Vectors
/** struct dccp_ackvec_record - Records information about sent Ack Vectors
...
@@ -98,29 +99,38 @@ struct dccp_ackvec_record {
...
@@ -98,29 +99,38 @@ struct dccp_ackvec_record {
u8
avr_ack_nonce
:
1
;
u8
avr_ack_nonce
:
1
;
};
};
struct
sock
;
struct
sk_buff
;
extern
int
dccp_ackvec_init
(
void
);
extern
int
dccp_ackvec_init
(
void
);
extern
void
dccp_ackvec_exit
(
void
);
extern
void
dccp_ackvec_exit
(
void
);
extern
struct
dccp_ackvec
*
dccp_ackvec_alloc
(
const
gfp_t
priority
);
extern
struct
dccp_ackvec
*
dccp_ackvec_alloc
(
const
gfp_t
priority
);
extern
void
dccp_ackvec_free
(
struct
dccp_ackvec
*
av
);
extern
void
dccp_ackvec_free
(
struct
dccp_ackvec
*
av
);
extern
int
dccp_ackvec_add
(
struct
dccp_ackvec
*
av
,
const
struct
sock
*
sk
,
extern
void
dccp_ackvec_input
(
struct
dccp_ackvec
*
av
,
struct
sk_buff
*
skb
);
const
u64
ackno
,
const
u8
state
);
extern
void
dccp_ackvec_check_rcv_ackno
(
struct
dccp_ackvec
*
av
,
struct
sock
*
sk
,
const
u64
ackno
);
extern
int
dccp_ackvec_parse
(
struct
sock
*
sk
,
const
struct
sk_buff
*
skb
,
u64
*
ackno
,
const
u8
opt
,
const
u8
*
value
,
const
u8
len
);
extern
int
dccp_ackvec_update_records
(
struct
dccp_ackvec
*
av
,
u64
seq
,
u8
sum
);
extern
int
dccp_ackvec_update_records
(
struct
dccp_ackvec
*
av
,
u64
seq
,
u8
sum
);
extern
void
dccp_ackvec_clear_state
(
struct
dccp_ackvec
*
av
,
const
u64
ackno
);
extern
u16
dccp_ackvec_buflen
(
const
struct
dccp_ackvec
*
av
);
extern
u16
dccp_ackvec_buflen
(
const
struct
dccp_ackvec
*
av
);
static
inline
bool
dccp_ackvec_is_empty
(
const
struct
dccp_ackvec
*
av
)
static
inline
bool
dccp_ackvec_is_empty
(
const
struct
dccp_ackvec
*
av
)
{
{
return
av
->
av_overflow
==
0
&&
av
->
av_buf_head
==
av
->
av_buf_tail
;
return
av
->
av_overflow
==
0
&&
av
->
av_buf_head
==
av
->
av_buf_tail
;
}
}
/**
* struct dccp_ackvec_parsed - Record offsets of Ack Vectors in skb
* @vec: start of vector (offset into skb)
* @len: length of @vec
* @nonce: whether @vec had an ECN nonce of 0 or 1
* @node: FIFO - arranged in descending order of ack_ackno
* This structure is used by CCIDs to access Ack Vectors in a received skb.
*/
struct
dccp_ackvec_parsed
{
u8
*
vec
,
len
,
nonce:
1
;
struct
list_head
node
;
};
extern
int
dccp_ackvec_parsed_add
(
struct
list_head
*
head
,
u8
*
vec
,
u8
len
,
u8
nonce
);
extern
void
dccp_ackvec_parsed_cleanup
(
struct
list_head
*
parsed_chunks
);
#endif
/* _ACKVEC_H */
#endif
/* _ACKVEC_H */
net/dccp/ccids/ccid2.c
View file @
6c1b6c6b
...
@@ -246,68 +246,6 @@ static void ccid2_hc_tx_packet_sent(struct sock *sk, unsigned int len)
...
@@ -246,68 +246,6 @@ static void ccid2_hc_tx_packet_sent(struct sock *sk, unsigned int len)
#endif
#endif
}
}
/* XXX Lame code duplication!
* returns -1 if none was found.
* else returns the next offset to use in the function call.
*/
static
int
ccid2_ackvector
(
struct
sock
*
sk
,
struct
sk_buff
*
skb
,
int
offset
,
unsigned
char
**
vec
,
unsigned
char
*
veclen
)
{
const
struct
dccp_hdr
*
dh
=
dccp_hdr
(
skb
);
unsigned
char
*
options
=
(
unsigned
char
*
)
dh
+
dccp_hdr_len
(
skb
);
unsigned
char
*
opt_ptr
;
const
unsigned
char
*
opt_end
=
(
unsigned
char
*
)
dh
+
(
dh
->
dccph_doff
*
4
);
unsigned
char
opt
,
len
;
unsigned
char
*
value
;
BUG_ON
(
offset
<
0
);
options
+=
offset
;
opt_ptr
=
options
;
if
(
opt_ptr
>=
opt_end
)
return
-
1
;
while
(
opt_ptr
!=
opt_end
)
{
opt
=
*
opt_ptr
++
;
len
=
0
;
value
=
NULL
;
/* Check if this isn't a single byte option */
if
(
opt
>
DCCPO_MAX_RESERVED
)
{
if
(
opt_ptr
==
opt_end
)
goto
out_invalid_option
;
len
=
*
opt_ptr
++
;
if
(
len
<
3
)
goto
out_invalid_option
;
/*
* Remove the type and len fields, leaving
* just the value size
*/
len
-=
2
;
value
=
opt_ptr
;
opt_ptr
+=
len
;
if
(
opt_ptr
>
opt_end
)
goto
out_invalid_option
;
}
switch
(
opt
)
{
case
DCCPO_ACK_VECTOR_0
:
case
DCCPO_ACK_VECTOR_1
:
*
vec
=
value
;
*
veclen
=
len
;
return
offset
+
(
opt_ptr
-
options
);
}
}
return
-
1
;
out_invalid_option:
DCCP_BUG
(
"Invalid option - this should not happen (previous parsing)!"
);
return
-
1
;
}
/**
/**
* ccid2_rtt_estimator - Sample RTT and compute RTO using RFC2988 algorithm
* ccid2_rtt_estimator - Sample RTT and compute RTO using RFC2988 algorithm
* This code is almost identical with TCP's tcp_rtt_estimator(), since
* This code is almost identical with TCP's tcp_rtt_estimator(), since
...
@@ -432,16 +370,28 @@ static void ccid2_congestion_event(struct sock *sk, struct ccid2_seq *seqp)
...
@@ -432,16 +370,28 @@ static void ccid2_congestion_event(struct sock *sk, struct ccid2_seq *seqp)
ccid2_change_l_ack_ratio
(
sk
,
hc
->
tx_cwnd
);
ccid2_change_l_ack_ratio
(
sk
,
hc
->
tx_cwnd
);
}
}
static
int
ccid2_hc_tx_parse_options
(
struct
sock
*
sk
,
u8
packet_type
,
u8
option
,
u8
*
optval
,
u8
optlen
)
{
struct
ccid2_hc_tx_sock
*
hc
=
ccid2_hc_tx_sk
(
sk
);
switch
(
option
)
{
case
DCCPO_ACK_VECTOR_0
:
case
DCCPO_ACK_VECTOR_1
:
return
dccp_ackvec_parsed_add
(
&
hc
->
tx_av_chunks
,
optval
,
optlen
,
option
-
DCCPO_ACK_VECTOR_0
);
}
return
0
;
}
static
void
ccid2_hc_tx_packet_recv
(
struct
sock
*
sk
,
struct
sk_buff
*
skb
)
static
void
ccid2_hc_tx_packet_recv
(
struct
sock
*
sk
,
struct
sk_buff
*
skb
)
{
{
struct
dccp_sock
*
dp
=
dccp_sk
(
sk
);
struct
dccp_sock
*
dp
=
dccp_sk
(
sk
);
struct
ccid2_hc_tx_sock
*
hc
=
ccid2_hc_tx_sk
(
sk
);
struct
ccid2_hc_tx_sock
*
hc
=
ccid2_hc_tx_sk
(
sk
);
const
bool
sender_was_blocked
=
ccid2_cwnd_network_limited
(
hc
);
const
bool
sender_was_blocked
=
ccid2_cwnd_network_limited
(
hc
);
struct
dccp_ackvec_parsed
*
avp
;
u64
ackno
,
seqno
;
u64
ackno
,
seqno
;
struct
ccid2_seq
*
seqp
;
struct
ccid2_seq
*
seqp
;
unsigned
char
*
vector
;
unsigned
char
veclen
;
int
offset
=
0
;
int
done
=
0
;
int
done
=
0
;
unsigned
int
maxincr
=
0
;
unsigned
int
maxincr
=
0
;
...
@@ -475,17 +425,12 @@ static void ccid2_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
...
@@ -475,17 +425,12 @@ static void ccid2_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
}
}
/* check forward path congestion */
/* check forward path congestion */
/* still didn't send out new data packets */
if
(
dccp_packet_without_ack
(
skb
))
if
(
hc
->
tx_seqh
==
hc
->
tx_seqt
)
return
;
return
;
switch
(
DCCP_SKB_CB
(
skb
)
->
dccpd_type
)
{
/* still didn't send out new data packets */
case
DCCP_PKT_ACK
:
if
(
hc
->
tx_seqh
==
hc
->
tx_seqt
)
case
DCCP_PKT_DATAACK
:
goto
done
;
break
;
default:
return
;
}
ackno
=
DCCP_SKB_CB
(
skb
)
->
dccpd_ack_seq
;
ackno
=
DCCP_SKB_CB
(
skb
)
->
dccpd_ack_seq
;
if
(
after48
(
ackno
,
hc
->
tx_high_ack
))
if
(
after48
(
ackno
,
hc
->
tx_high_ack
))
...
@@ -509,15 +454,16 @@ static void ccid2_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
...
@@ -509,15 +454,16 @@ static void ccid2_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
maxincr
=
DIV_ROUND_UP
(
dp
->
dccps_l_ack_ratio
,
2
);
maxincr
=
DIV_ROUND_UP
(
dp
->
dccps_l_ack_ratio
,
2
);
/* go through all ack vectors */
/* go through all ack vectors */
while
((
offset
=
ccid2_ackvector
(
sk
,
skb
,
offset
,
list_for_each_entry
(
avp
,
&
hc
->
tx_av_chunks
,
node
)
{
&
vector
,
&
veclen
))
!=
-
1
)
{
/* go through this ack vector */
/* go through this ack vector */
while
(
veclen
--
)
{
for
(;
avp
->
len
--
;
avp
->
vec
++
)
{
u64
ackno_end_rl
=
SUB48
(
ackno
,
dccp_ackvec_runlen
(
vector
));
u64
ackno_end_rl
=
SUB48
(
ackno
,
dccp_ackvec_runlen
(
avp
->
vec
));
ccid2_pr_debug
(
"ackvec
start:%llu end:%llu
\n
"
,
ccid2_pr_debug
(
"ackvec
%llu |%u,%u|
\n
"
,
(
unsigned
long
long
)
ackno
,
(
unsigned
long
long
)
ackno
,
(
unsigned
long
long
)
ackno_end_rl
);
dccp_ackvec_state
(
avp
->
vec
)
>>
6
,
dccp_ackvec_runlen
(
avp
->
vec
));
/* if the seqno we are analyzing is larger than the
/* if the seqno we are analyzing is larger than the
* current ackno, then move towards the tail of our
* current ackno, then move towards the tail of our
* seqnos.
* seqnos.
...
@@ -536,7 +482,7 @@ static void ccid2_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
...
@@ -536,7 +482,7 @@ static void ccid2_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
* run length
* run length
*/
*/
while
(
between48
(
seqp
->
ccid2s_seq
,
ackno_end_rl
,
ackno
))
{
while
(
between48
(
seqp
->
ccid2s_seq
,
ackno_end_rl
,
ackno
))
{
const
u8
state
=
dccp_ackvec_state
(
vector
);
const
u8
state
=
dccp_ackvec_state
(
avp
->
vec
);
/* new packet received or marked */
/* new packet received or marked */
if
(
state
!=
DCCPAV_NOT_RECEIVED
&&
if
(
state
!=
DCCPAV_NOT_RECEIVED
&&
...
@@ -563,7 +509,6 @@ static void ccid2_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
...
@@ -563,7 +509,6 @@ static void ccid2_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
break
;
break
;
ackno
=
SUB48
(
ackno_end_rl
,
1
);
ackno
=
SUB48
(
ackno_end_rl
,
1
);
vector
++
;
}
}
if
(
done
)
if
(
done
)
break
;
break
;
...
@@ -631,10 +576,11 @@ static void ccid2_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
...
@@ -631,10 +576,11 @@ static void ccid2_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
sk_stop_timer
(
sk
,
&
hc
->
tx_rtotimer
);
sk_stop_timer
(
sk
,
&
hc
->
tx_rtotimer
);
else
else
sk_reset_timer
(
sk
,
&
hc
->
tx_rtotimer
,
jiffies
+
hc
->
tx_rto
);
sk_reset_timer
(
sk
,
&
hc
->
tx_rtotimer
,
jiffies
+
hc
->
tx_rto
);
done:
/* check if incoming Acks allow pending packets to be sent */
/* check if incoming Acks allow pending packets to be sent */
if
(
sender_was_blocked
&&
!
ccid2_cwnd_network_limited
(
hc
))
if
(
sender_was_blocked
&&
!
ccid2_cwnd_network_limited
(
hc
))
tasklet_schedule
(
&
dccp_sk
(
sk
)
->
dccps_xmitlet
);
tasklet_schedule
(
&
dccp_sk
(
sk
)
->
dccps_xmitlet
);
dccp_ackvec_parsed_cleanup
(
&
hc
->
tx_av_chunks
);
}
}
static
int
ccid2_hc_tx_init
(
struct
ccid
*
ccid
,
struct
sock
*
sk
)
static
int
ccid2_hc_tx_init
(
struct
ccid
*
ccid
,
struct
sock
*
sk
)
...
@@ -663,6 +609,7 @@ static int ccid2_hc_tx_init(struct ccid *ccid, struct sock *sk)
...
@@ -663,6 +609,7 @@ static int ccid2_hc_tx_init(struct ccid *ccid, struct sock *sk)
hc
->
tx_last_cong
=
ccid2_time_stamp
;
hc
->
tx_last_cong
=
ccid2_time_stamp
;
setup_timer
(
&
hc
->
tx_rtotimer
,
ccid2_hc_tx_rto_expire
,
setup_timer
(
&
hc
->
tx_rtotimer
,
ccid2_hc_tx_rto_expire
,
(
unsigned
long
)
sk
);
(
unsigned
long
)
sk
);
INIT_LIST_HEAD
(
&
hc
->
tx_av_chunks
);
return
0
;
return
0
;
}
}
...
@@ -703,6 +650,7 @@ struct ccid_operations ccid2_ops = {
...
@@ -703,6 +650,7 @@ struct ccid_operations ccid2_ops = {
.
ccid_hc_tx_exit
=
ccid2_hc_tx_exit
,
.
ccid_hc_tx_exit
=
ccid2_hc_tx_exit
,
.
ccid_hc_tx_send_packet
=
ccid2_hc_tx_send_packet
,
.
ccid_hc_tx_send_packet
=
ccid2_hc_tx_send_packet
,
.
ccid_hc_tx_packet_sent
=
ccid2_hc_tx_packet_sent
,
.
ccid_hc_tx_packet_sent
=
ccid2_hc_tx_packet_sent
,
.
ccid_hc_tx_parse_options
=
ccid2_hc_tx_parse_options
,
.
ccid_hc_tx_packet_recv
=
ccid2_hc_tx_packet_recv
,
.
ccid_hc_tx_packet_recv
=
ccid2_hc_tx_packet_recv
,
.
ccid_hc_rx_obj_size
=
sizeof
(
struct
ccid2_hc_rx_sock
),
.
ccid_hc_rx_obj_size
=
sizeof
(
struct
ccid2_hc_rx_sock
),
.
ccid_hc_rx_packet_recv
=
ccid2_hc_rx_packet_recv
,
.
ccid_hc_rx_packet_recv
=
ccid2_hc_rx_packet_recv
,
...
...
net/dccp/ccids/ccid2.h
View file @
6c1b6c6b
...
@@ -55,6 +55,7 @@ struct ccid2_seq {
...
@@ -55,6 +55,7 @@ struct ccid2_seq {
* @tx_rtt_seq: to decay RTTVAR at most once per flight
* @tx_rtt_seq: to decay RTTVAR at most once per flight
* @tx_rpseq: last consecutive seqno
* @tx_rpseq: last consecutive seqno
* @tx_rpdupack: dupacks since rpseq
* @tx_rpdupack: dupacks since rpseq
* @tx_av_chunks: list of Ack Vectors received on current skb
*/
*/
struct
ccid2_hc_tx_sock
{
struct
ccid2_hc_tx_sock
{
u32
tx_cwnd
;
u32
tx_cwnd
;
...
@@ -79,6 +80,7 @@ struct ccid2_hc_tx_sock {
...
@@ -79,6 +80,7 @@ struct ccid2_hc_tx_sock {
int
tx_rpdupack
;
int
tx_rpdupack
;
u32
tx_last_cong
;
u32
tx_last_cong
;
u64
tx_high_ack
;
u64
tx_high_ack
;
struct
list_head
tx_av_chunks
;
};
};
static
inline
bool
ccid2_cwnd_network_limited
(
struct
ccid2_hc_tx_sock
*
hc
)
static
inline
bool
ccid2_cwnd_network_limited
(
struct
ccid2_hc_tx_sock
*
hc
)
...
...
net/dccp/input.c
View file @
6c1b6c6b
...
@@ -160,13 +160,15 @@ static void dccp_rcv_reset(struct sock *sk, struct sk_buff *skb)
...
@@ -160,13 +160,15 @@ static void dccp_rcv_reset(struct sock *sk, struct sk_buff *skb)
dccp_time_wait
(
sk
,
DCCP_TIME_WAIT
,
0
);
dccp_time_wait
(
sk
,
DCCP_TIME_WAIT
,
0
);
}
}
static
void
dccp_
event_ack_recv
(
struct
sock
*
sk
,
struct
sk_buff
*
skb
)
static
void
dccp_
handle_ackvec_processing
(
struct
sock
*
sk
,
struct
sk_buff
*
skb
)
{
{
struct
dccp_
sock
*
dp
=
dccp_sk
(
sk
)
;
struct
dccp_
ackvec
*
av
=
dccp_sk
(
sk
)
->
dccps_hc_rx_ackvec
;
if
(
dp
->
dccps_hc_rx_ackvec
!=
NULL
)
if
(
av
==
NULL
)
dccp_ackvec_check_rcv_ackno
(
dp
->
dccps_hc_rx_ackvec
,
sk
,
return
;
DCCP_SKB_CB
(
skb
)
->
dccpd_ack_seq
);
if
(
DCCP_SKB_CB
(
skb
)
->
dccpd_ack_seq
!=
DCCP_PKT_WITHOUT_ACK_SEQ
)
dccp_ackvec_clear_state
(
av
,
DCCP_SKB_CB
(
skb
)
->
dccpd_ack_seq
);
dccp_ackvec_input
(
av
,
skb
);
}
}
static
void
dccp_deliver_input_to_ccids
(
struct
sock
*
sk
,
struct
sk_buff
*
skb
)
static
void
dccp_deliver_input_to_ccids
(
struct
sock
*
sk
,
struct
sk_buff
*
skb
)
...
@@ -365,21 +367,13 @@ static int __dccp_rcv_established(struct sock *sk, struct sk_buff *skb,
...
@@ -365,21 +367,13 @@ static int __dccp_rcv_established(struct sock *sk, struct sk_buff *skb,
int
dccp_rcv_established
(
struct
sock
*
sk
,
struct
sk_buff
*
skb
,
int
dccp_rcv_established
(
struct
sock
*
sk
,
struct
sk_buff
*
skb
,
const
struct
dccp_hdr
*
dh
,
const
unsigned
len
)
const
struct
dccp_hdr
*
dh
,
const
unsigned
len
)
{
{
struct
dccp_sock
*
dp
=
dccp_sk
(
sk
);
if
(
dccp_check_seqno
(
sk
,
skb
))
if
(
dccp_check_seqno
(
sk
,
skb
))
goto
discard
;
goto
discard
;
if
(
dccp_parse_options
(
sk
,
NULL
,
skb
))
if
(
dccp_parse_options
(
sk
,
NULL
,
skb
))
return
1
;
return
1
;
if
(
DCCP_SKB_CB
(
skb
)
->
dccpd_ack_seq
!=
DCCP_PKT_WITHOUT_ACK_SEQ
)
dccp_handle_ackvec_processing
(
sk
,
skb
);
dccp_event_ack_recv
(
sk
,
skb
);
if
(
dp
->
dccps_hc_rx_ackvec
!=
NULL
&&
dccp_ackvec_add
(
dp
->
dccps_hc_rx_ackvec
,
sk
,
DCCP_SKB_CB
(
skb
)
->
dccpd_seq
,
DCCPAV_RECEIVED
))
goto
discard
;
dccp_deliver_input_to_ccids
(
sk
,
skb
);
dccp_deliver_input_to_ccids
(
sk
,
skb
);
return
__dccp_rcv_established
(
sk
,
skb
,
dh
,
len
);
return
__dccp_rcv_established
(
sk
,
skb
,
dh
,
len
);
...
@@ -631,14 +625,7 @@ int dccp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
...
@@ -631,14 +625,7 @@ int dccp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
if
(
dccp_parse_options
(
sk
,
NULL
,
skb
))
if
(
dccp_parse_options
(
sk
,
NULL
,
skb
))
return
1
;
return
1
;
if
(
dcb
->
dccpd_ack_seq
!=
DCCP_PKT_WITHOUT_ACK_SEQ
)
dccp_handle_ackvec_processing
(
sk
,
skb
);
dccp_event_ack_recv
(
sk
,
skb
);
if
(
dp
->
dccps_hc_rx_ackvec
!=
NULL
&&
dccp_ackvec_add
(
dp
->
dccps_hc_rx_ackvec
,
sk
,
DCCP_SKB_CB
(
skb
)
->
dccpd_seq
,
DCCPAV_RECEIVED
))
goto
discard
;
dccp_deliver_input_to_ccids
(
sk
,
skb
);
dccp_deliver_input_to_ccids
(
sk
,
skb
);
}
}
...
...
net/dccp/options.c
View file @
6c1b6c6b
...
@@ -54,7 +54,6 @@ int dccp_parse_options(struct sock *sk, struct dccp_request_sock *dreq,
...
@@ -54,7 +54,6 @@ int dccp_parse_options(struct sock *sk, struct dccp_request_sock *dreq,
struct
dccp_sock
*
dp
=
dccp_sk
(
sk
);
struct
dccp_sock
*
dp
=
dccp_sk
(
sk
);
const
struct
dccp_hdr
*
dh
=
dccp_hdr
(
skb
);
const
struct
dccp_hdr
*
dh
=
dccp_hdr
(
skb
);
const
u8
pkt_type
=
DCCP_SKB_CB
(
skb
)
->
dccpd_type
;
const
u8
pkt_type
=
DCCP_SKB_CB
(
skb
)
->
dccpd_type
;
u64
ackno
=
DCCP_SKB_CB
(
skb
)
->
dccpd_ack_seq
;
unsigned
char
*
options
=
(
unsigned
char
*
)
dh
+
dccp_hdr_len
(
skb
);
unsigned
char
*
options
=
(
unsigned
char
*
)
dh
+
dccp_hdr_len
(
skb
);
unsigned
char
*
opt_ptr
=
options
;
unsigned
char
*
opt_ptr
=
options
;
const
unsigned
char
*
opt_end
=
(
unsigned
char
*
)
dh
+
const
unsigned
char
*
opt_end
=
(
unsigned
char
*
)
dh
+
...
@@ -129,14 +128,6 @@ int dccp_parse_options(struct sock *sk, struct dccp_request_sock *dreq,
...
@@ -129,14 +128,6 @@ int dccp_parse_options(struct sock *sk, struct dccp_request_sock *dreq,
if
(
rc
)
if
(
rc
)
goto
out_featneg_failed
;
goto
out_featneg_failed
;
break
;
break
;
case
DCCPO_ACK_VECTOR_0
:
case
DCCPO_ACK_VECTOR_1
:
if
(
dccp_packet_without_ack
(
skb
))
/* RFC 4340, 11.4 */
break
;
if
(
dp
->
dccps_hc_rx_ackvec
!=
NULL
&&
dccp_ackvec_parse
(
sk
,
skb
,
&
ackno
,
opt
,
value
,
len
))
goto
out_invalid_option
;
break
;
case
DCCPO_TIMESTAMP
:
case
DCCPO_TIMESTAMP
:
if
(
len
!=
4
)
if
(
len
!=
4
)
goto
out_invalid_option
;
goto
out_invalid_option
;
...
@@ -226,6 +217,16 @@ int dccp_parse_options(struct sock *sk, struct dccp_request_sock *dreq,
...
@@ -226,6 +217,16 @@ int dccp_parse_options(struct sock *sk, struct dccp_request_sock *dreq,
pkt_type
,
opt
,
value
,
len
))
pkt_type
,
opt
,
value
,
len
))
goto
out_invalid_option
;
goto
out_invalid_option
;
break
;
break
;
case
DCCPO_ACK_VECTOR_0
:
case
DCCPO_ACK_VECTOR_1
:
if
(
dccp_packet_without_ack
(
skb
))
/* RFC 4340, 11.4 */
break
;
/*
* Ack vectors are processed by the TX CCID if it is
* interested. The RX CCID need not parse Ack Vectors,
* since it is only interested in clearing old state.
* Fall through.
*/
case
DCCPO_MIN_TX_CCID_SPECIFIC
...
DCCPO_MAX_TX_CCID_SPECIFIC
:
case
DCCPO_MIN_TX_CCID_SPECIFIC
...
DCCPO_MAX_TX_CCID_SPECIFIC
:
if
(
ccid_hc_tx_parse_options
(
dp
->
dccps_hc_tx_ccid
,
sk
,
if
(
ccid_hc_tx_parse_options
(
dp
->
dccps_hc_tx_ccid
,
sk
,
pkt_type
,
opt
,
value
,
len
))
pkt_type
,
opt
,
value
,
len
))
...
@@ -429,6 +430,7 @@ static int dccp_insert_option_ackvec(struct sock *sk, struct sk_buff *skb)
...
@@ -429,6 +430,7 @@ static int dccp_insert_option_ackvec(struct sock *sk, struct sk_buff *skb)
{
{
struct
dccp_sock
*
dp
=
dccp_sk
(
sk
);
struct
dccp_sock
*
dp
=
dccp_sk
(
sk
);
struct
dccp_ackvec
*
av
=
dp
->
dccps_hc_rx_ackvec
;
struct
dccp_ackvec
*
av
=
dp
->
dccps_hc_rx_ackvec
;
struct
dccp_skb_cb
*
dcb
=
DCCP_SKB_CB
(
skb
);
const
u16
buflen
=
dccp_ackvec_buflen
(
av
);
const
u16
buflen
=
dccp_ackvec_buflen
(
av
);
/* Figure out how many options do we need to represent the ackvec */
/* Figure out how many options do we need to represent the ackvec */
const
u8
nr_opts
=
DIV_ROUND_UP
(
buflen
,
DCCP_SINGLE_OPT_MAXLEN
);
const
u8
nr_opts
=
DIV_ROUND_UP
(
buflen
,
DCCP_SINGLE_OPT_MAXLEN
);
...
@@ -437,10 +439,25 @@ static int dccp_insert_option_ackvec(struct sock *sk, struct sk_buff *skb)
...
@@ -437,10 +439,25 @@ static int dccp_insert_option_ackvec(struct sock *sk, struct sk_buff *skb)
const
unsigned
char
*
tail
,
*
from
;
const
unsigned
char
*
tail
,
*
from
;
unsigned
char
*
to
;
unsigned
char
*
to
;
if
(
DCCP_SKB_CB
(
skb
)
->
dccpd_opt_len
+
len
>
DCCP_MAX_OPT_LEN
)
if
(
dcb
->
dccpd_opt_len
+
len
>
DCCP_MAX_OPT_LEN
)
{
DCCP_WARN
(
"Lacking space for %u bytes on %s packet
\n
"
,
len
,
dccp_packet_name
(
dcb
->
dccpd_type
));
return
-
1
;
return
-
1
;
}
DCCP_SKB_CB
(
skb
)
->
dccpd_opt_len
+=
len
;
/*
* Since Ack Vectors are variable-length, we can not always predict
* their size. To catch exception cases where the space is running out
* on the skb, a separate Sync is scheduled to carry the Ack Vector.
*/
if
(
len
>
DCCPAV_MIN_OPTLEN
&&
len
+
dcb
->
dccpd_opt_len
+
skb
->
len
>
dp
->
dccps_mss_cache
)
{
DCCP_WARN
(
"No space left for Ack Vector (%u) on skb (%u+%u), "
"MPS=%u ==> reduce payload size?
\n
"
,
len
,
skb
->
len
,
dcb
->
dccpd_opt_len
,
dp
->
dccps_mss_cache
);
dp
->
dccps_sync_scheduled
=
1
;
return
0
;
}
dcb
->
dccpd_opt_len
+=
len
;
to
=
skb_push
(
skb
,
len
);
to
=
skb_push
(
skb
,
len
);
len
=
buflen
;
len
=
buflen
;
...
@@ -481,7 +498,7 @@ static int dccp_insert_option_ackvec(struct sock *sk, struct sk_buff *skb)
...
@@ -481,7 +498,7 @@ static int dccp_insert_option_ackvec(struct sock *sk, struct sk_buff *skb)
/*
/*
* Each sent Ack Vector is recorded in the list, as per A.2 of RFC 4340.
* Each sent Ack Vector is recorded in the list, as per A.2 of RFC 4340.
*/
*/
if
(
dccp_ackvec_update_records
(
av
,
DCCP_SKB_CB
(
skb
)
->
dccpd_seq
,
nonce
))
if
(
dccp_ackvec_update_records
(
av
,
dcb
->
dccpd_seq
,
nonce
))
return
-
ENOBUFS
;
return
-
ENOBUFS
;
return
0
;
return
0
;
}
}
...
...
net/dccp/output.c
View file @
6c1b6c6b
...
@@ -283,6 +283,15 @@ static void dccp_xmit_packet(struct sock *sk)
...
@@ -283,6 +283,15 @@ static void dccp_xmit_packet(struct sock *sk)
* any local drop will eventually be reported via receiver feedback.
* any local drop will eventually be reported via receiver feedback.
*/
*/
ccid_hc_tx_packet_sent
(
dp
->
dccps_hc_tx_ccid
,
sk
,
len
);
ccid_hc_tx_packet_sent
(
dp
->
dccps_hc_tx_ccid
,
sk
,
len
);
/*
* If the CCID needs to transfer additional header options out-of-band
* (e.g. Ack Vectors or feature-negotiation options), it activates this
* flag to schedule a Sync. The Sync will automatically incorporate all
* currently pending header options, thus clearing the backlog.
*/
if
(
dp
->
dccps_sync_scheduled
)
dccp_send_sync
(
sk
,
dp
->
dccps_gsr
,
DCCP_PKT_SYNC
);
}
}
/**
/**
...
@@ -636,6 +645,12 @@ void dccp_send_sync(struct sock *sk, const u64 ackno,
...
@@ -636,6 +645,12 @@ void dccp_send_sync(struct sock *sk, const u64 ackno,
DCCP_SKB_CB
(
skb
)
->
dccpd_type
=
pkt_type
;
DCCP_SKB_CB
(
skb
)
->
dccpd_type
=
pkt_type
;
DCCP_SKB_CB
(
skb
)
->
dccpd_ack_seq
=
ackno
;
DCCP_SKB_CB
(
skb
)
->
dccpd_ack_seq
=
ackno
;
/*
* Clear the flag in case the Sync was scheduled for out-of-band data,
* such as carrying a long Ack Vector.
*/
dccp_sk
(
sk
)
->
dccps_sync_scheduled
=
0
;
dccp_transmit_skb
(
sk
,
skb
);
dccp_transmit_skb
(
sk
,
skb
);
}
}
...
...
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