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
7fedd7e5
Commit
7fedd7e5
authored
Sep 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
1a19eb75
37efb03f
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
73 additions
and
119 deletions
+73
-119
net/dccp/ccids/ccid3.c
net/dccp/ccids/ccid3.c
+41
-69
net/dccp/ccids/ccid3.h
net/dccp/ccids/ccid3.h
+13
-8
net/dccp/ccids/lib/packet_history.c
net/dccp/ccids/lib/packet_history.c
+0
-39
net/dccp/ccids/lib/packet_history.h
net/dccp/ccids/lib/packet_history.h
+19
-3
No files found.
net/dccp/ccids/ccid3.c
View file @
7fedd7e5
...
...
@@ -91,19 +91,16 @@ static inline u64 rfc3390_initial_rate(struct sock *sk)
return
scaled_div
(
w_init
<<
6
,
hc
->
tx_rtt
);
}
/*
* Recalculate t_ipi and delta (should be called whenever X changes)
/**
* ccid3_update_send_interval - Calculate new t_ipi = s / X_inst
* This respects the granularity of X_inst (64 * bytes/second).
*/
static
void
ccid3_update_send_interval
(
struct
ccid3_hc_tx_sock
*
hc
)
{
/* Calculate new t_ipi = s / X_inst (X_inst is in 64 * bytes/second) */
hc
->
tx_t_ipi
=
scaled_div32
(((
u64
)
hc
->
tx_s
)
<<
6
,
hc
->
tx_x
);
/* Calculate new delta by delta = min(t_ipi / 2, t_gran / 2) */
hc
->
tx_delta
=
min_t
(
u32
,
hc
->
tx_t_ipi
/
2
,
TFRC_OPSYS_HALF_TIME_GRAN
);
ccid3_pr_debug
(
"t_ipi=%u, delta=%u, s=%u, X=%u
\n
"
,
hc
->
tx_t_ipi
,
hc
->
tx_delta
,
hc
->
tx_s
,
(
unsigned
)(
hc
->
tx_x
>>
6
));
ccid3_pr_debug
(
"t_ipi=%u, s=%u, X=%u
\n
"
,
hc
->
tx_t_ipi
,
hc
->
tx_s
,
(
unsigned
)(
hc
->
tx_x
>>
6
));
}
static
u32
ccid3_hc_tx_idle_rtt
(
struct
ccid3_hc_tx_sock
*
hc
,
ktime_t
now
)
...
...
@@ -332,15 +329,15 @@ static int ccid3_hc_tx_send_packet(struct sock *sk, struct sk_buff *skb)
delay
=
ktime_us_delta
(
hc
->
tx_t_nom
,
now
);
ccid3_pr_debug
(
"delay=%ld
\n
"
,
(
long
)
delay
);
/*
* Scheduling of packet transmissions
[RFC 3448, 4.6]
* Scheduling of packet transmissions
(RFC 5348, 8.3)
*
* if (t_now > t_nom - delta)
* // send the packet now
* else
* // send the packet in (t_nom - t_now) milliseconds.
*/
if
(
delay
-
(
s64
)
hc
->
tx_delta
>=
1000
)
return
(
u32
)
delay
/
1000L
;
if
(
delay
>=
TFRC_T_DELTA
)
return
(
u32
)
delay
/
USEC_PER_MSEC
;
ccid3_hc_tx_update_win_count
(
hc
,
now
);
break
;
...
...
@@ -373,6 +370,7 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
{
struct
ccid3_hc_tx_sock
*
hc
=
ccid3_hc_tx_sk
(
sk
);
struct
ccid3_options_received
*
opt_recv
=
&
hc
->
tx_options_received
;
struct
tfrc_tx_hist_entry
*
acked
;
ktime_t
now
;
unsigned
long
t_nfb
;
u32
pinv
,
r_sample
;
...
...
@@ -386,17 +384,24 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
hc
->
tx_state
!=
TFRC_SSTATE_NO_FBACK
)
return
;
now
=
ktime_get_real
();
/* Estimate RTT from history if ACK number is valid */
r_sample
=
tfrc_tx_hist_rtt
(
hc
->
tx_hist
,
DCCP_SKB_CB
(
skb
)
->
dccpd_ack_seq
,
now
);
if
(
r_sample
==
0
)
{
DCCP_WARN
(
"%s(%p): %s with bogus ACK-%llu
\n
"
,
dccp_role
(
sk
),
sk
,
dccp_packet_name
(
DCCP_SKB_CB
(
skb
)
->
dccpd_type
),
(
unsigned
long
long
)
DCCP_SKB_CB
(
skb
)
->
dccpd_ack_seq
);
/*
* Locate the acknowledged packet in the TX history.
*
* Returning "entry not found" here can for instance happen when
* - the host has not sent out anything (e.g. a passive server),
* - the Ack is outdated (packet with higher Ack number was received),
* - it is a bogus Ack (for a packet not sent on this connection).
*/
acked
=
tfrc_tx_hist_find_entry
(
hc
->
tx_hist
,
dccp_hdr_ack_seq
(
skb
));
if
(
acked
==
NULL
)
return
;
}
/* For the sake of RTT sampling, ignore/remove all older entries */
tfrc_tx_hist_purge
(
&
acked
->
next
);
/* Update the moving average for the RTT estimate (RFC 3448, 4.3) */
now
=
ktime_get_real
();
r_sample
=
dccp_sample_rtt
(
sk
,
ktime_us_delta
(
now
,
acked
->
stamp
));
hc
->
tx_rtt
=
tfrc_ewma
(
hc
->
tx_rtt
,
r_sample
,
9
);
/* Update receive rate in units of 64 * bytes/second */
hc
->
tx_x_recv
=
opt_recv
->
ccid3or_receive_rate
;
...
...
@@ -408,11 +413,7 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
hc
->
tx_p
=
0
;
else
/* can not exceed 100% */
hc
->
tx_p
=
scaled_div
(
1
,
pinv
);
/*
* Validate new RTT sample and update moving average
*/
r_sample
=
dccp_sample_rtt
(
sk
,
r_sample
);
hc
->
tx_rtt
=
tfrc_ewma
(
hc
->
tx_rtt
,
r_sample
,
9
);
/*
* Update allowed sending rate X as per draft rfc3448bis-00, 4.2/3
*/
...
...
@@ -484,60 +485,31 @@ static int ccid3_hc_tx_parse_options(struct sock *sk, unsigned char option,
unsigned
char
len
,
u16
idx
,
unsigned
char
*
value
)
{
int
rc
=
0
;
const
struct
dccp_sock
*
dp
=
dccp_sk
(
sk
);
struct
ccid3_hc_tx_sock
*
hc
=
ccid3_hc_tx_sk
(
sk
);
struct
ccid3_options_received
*
opt_recv
=
&
hc
->
tx_options_received
;
__be32
opt_val
;
if
(
opt_recv
->
ccid3or_seqno
!=
dp
->
dccps_gsr
)
{
opt_recv
->
ccid3or_seqno
=
dp
->
dccps_gsr
;
opt_recv
->
ccid3or_loss_event_rate
=
~
0
;
opt_recv
->
ccid3or_loss_intervals_idx
=
0
;
opt_recv
->
ccid3or_loss_intervals_len
=
0
;
opt_recv
->
ccid3or_receive_rate
=
0
;
}
switch
(
option
)
{
case
TFRC_OPT_RECEIVE_RATE
:
case
TFRC_OPT_LOSS_EVENT_RATE
:
if
(
unlikely
(
len
!=
4
))
{
DCCP_WARN
(
"%s(%p), invalid len %d "
"for TFRC_OPT_LOSS_EVENT_RATE
\n
"
,
dccp_role
(
sk
),
sk
,
len
);
rc
=
-
EINVAL
;
}
else
{
opt_val
=
get_unaligned
((
__be32
*
)
value
);
opt_recv
->
ccid3or_loss_event_rate
=
ntohl
(
opt_val
);
ccid3_pr_debug
(
"%s(%p), LOSS_EVENT_RATE=%u
\n
"
,
dccp_role
(
sk
),
sk
,
opt_recv
->
ccid3or_loss_event_rate
);
DCCP_WARN
(
"%s(%p), invalid len %d for %u
\n
"
,
dccp_role
(
sk
),
sk
,
len
,
option
);
return
-
EINVAL
;
}
break
;
case
TFRC_OPT_LOSS_INTERVALS
:
opt_recv
->
ccid3or_loss_intervals_idx
=
idx
;
opt_recv
->
ccid3or_loss_intervals_len
=
len
;
ccid3_pr_debug
(
"%s(%p), LOSS_INTERVALS=(%u, %u)
\n
"
,
dccp_role
(
sk
),
sk
,
opt_recv
->
ccid3or_loss_intervals_idx
,
opt_recv
->
ccid3or_loss_intervals_len
);
break
;
case
TFRC_OPT_RECEIVE_RATE
:
if
(
unlikely
(
len
!=
4
))
{
DCCP_WARN
(
"%s(%p), invalid len %d "
"for TFRC_OPT_RECEIVE_RATE
\n
"
,
dccp_role
(
sk
),
sk
,
len
);
rc
=
-
EINVAL
;
}
else
{
opt_val
=
get_unaligned
((
__be32
*
)
value
);
opt_recv
->
ccid3or_receive_rate
=
ntohl
(
opt_val
);
opt_val
=
ntohl
(
get_unaligned
((
__be32
*
)
value
));
if
(
option
==
TFRC_OPT_RECEIVE_RATE
)
{
opt_recv
->
ccid3or_receive_rate
=
opt_val
;
ccid3_pr_debug
(
"%s(%p), RECEIVE_RATE=%u
\n
"
,
dccp_role
(
sk
),
sk
,
opt_recv
->
ccid3or_receive_rate
);
dccp_role
(
sk
),
sk
,
opt_val
);
}
else
{
opt_recv
->
ccid3or_loss_event_rate
=
opt_val
;
ccid3_pr_debug
(
"%s(%p), LOSS_EVENT_RATE=%u
\n
"
,
dccp_role
(
sk
),
sk
,
opt_val
);
}
break
;
}
return
rc
;
return
0
;
}
static
int
ccid3_hc_tx_init
(
struct
ccid
*
ccid
,
struct
sock
*
sk
)
...
...
net/dccp/ccids/ccid3.h
View file @
7fedd7e5
...
...
@@ -45,12 +45,22 @@
/* Two seconds as per RFC 5348, 4.2 */
#define TFRC_INITIAL_TIMEOUT (2 * USEC_PER_SEC)
/* In usecs - half the scheduling granularity as per RFC3448 4.6 */
#define TFRC_OPSYS_HALF_TIME_GRAN (USEC_PER_SEC / (2 * HZ))
/* Parameter t_mbi from [RFC 3448, 4.3]: backoff interval in seconds */
#define TFRC_T_MBI 64
/*
* The t_delta parameter (RFC 5348, 8.3): delays of less than %USEC_PER_MSEC are
* rounded down to 0, since sk_reset_timer() here uses millisecond granularity.
* Hence we can use a constant t_delta = %USEC_PER_MSEC when HZ >= 500. A coarse
* resolution of HZ < 500 means that the error is below one timer tick (t_gran)
* when using the constant t_delta = t_gran / 2 = %USEC_PER_SEC / (2 * HZ).
*/
#if (HZ >= 500)
# define TFRC_T_DELTA USEC_PER_MSEC
#else
# define TFRC_T_DELTA (USEC_PER_SEC / (2 * HZ))
#endif
enum
ccid3_options
{
TFRC_OPT_LOSS_EVENT_RATE
=
192
,
TFRC_OPT_LOSS_INTERVALS
=
193
,
...
...
@@ -58,9 +68,6 @@ enum ccid3_options {
};
struct
ccid3_options_received
{
u64
ccid3or_seqno
:
48
,
ccid3or_loss_intervals_idx:
16
;
u16
ccid3or_loss_intervals_len
;
u32
ccid3or_loss_event_rate
;
u32
ccid3or_receive_rate
;
};
...
...
@@ -90,7 +97,6 @@ enum ccid3_hc_tx_states {
* @tx_no_feedback_timer: Handle to no feedback timer
* @tx_t_ld: Time last doubled during slow start
* @tx_t_nom: Nominal send time of next packet
* @tx_delta: Send timer delta (RFC 3448, 4.6) in usecs
* @tx_hist: Packet history
* @tx_options_received: Parsed set of retrieved options
*/
...
...
@@ -109,7 +115,6 @@ struct ccid3_hc_tx_sock {
struct
timer_list
tx_no_feedback_timer
;
ktime_t
tx_t_ld
;
ktime_t
tx_t_nom
;
u32
tx_delta
;
struct
tfrc_tx_hist_entry
*
tx_hist
;
struct
ccid3_options_received
tx_options_received
;
};
...
...
net/dccp/ccids/lib/packet_history.c
View file @
7fedd7e5
...
...
@@ -38,18 +38,6 @@
#include "packet_history.h"
#include "../../dccp.h"
/**
* tfrc_tx_hist_entry - Simple singly-linked TX history list
* @next: next oldest entry (LIFO order)
* @seqno: sequence number of this entry
* @stamp: send time of packet with sequence number @seqno
*/
struct
tfrc_tx_hist_entry
{
struct
tfrc_tx_hist_entry
*
next
;
u64
seqno
;
ktime_t
stamp
;
};
/*
* Transmitter History Routines
*/
...
...
@@ -71,15 +59,6 @@ void tfrc_tx_packet_history_exit(void)
}
}
static
struct
tfrc_tx_hist_entry
*
tfrc_tx_hist_find_entry
(
struct
tfrc_tx_hist_entry
*
head
,
u64
seqno
)
{
while
(
head
!=
NULL
&&
head
->
seqno
!=
seqno
)
head
=
head
->
next
;
return
head
;
}
int
tfrc_tx_hist_add
(
struct
tfrc_tx_hist_entry
**
headp
,
u64
seqno
)
{
struct
tfrc_tx_hist_entry
*
entry
=
kmem_cache_alloc
(
tfrc_tx_hist_slab
,
gfp_any
());
...
...
@@ -107,24 +86,6 @@ void tfrc_tx_hist_purge(struct tfrc_tx_hist_entry **headp)
*
headp
=
NULL
;
}
u32
tfrc_tx_hist_rtt
(
struct
tfrc_tx_hist_entry
*
head
,
const
u64
seqno
,
const
ktime_t
now
)
{
u32
rtt
=
0
;
struct
tfrc_tx_hist_entry
*
packet
=
tfrc_tx_hist_find_entry
(
head
,
seqno
);
if
(
packet
!=
NULL
)
{
rtt
=
ktime_us_delta
(
now
,
packet
->
stamp
);
/*
* Garbage-collect older (irrelevant) entries:
*/
tfrc_tx_hist_purge
(
&
packet
->
next
);
}
return
rtt
;
}
/*
* Receiver History Routines
*/
...
...
net/dccp/ccids/lib/packet_history.h
View file @
7fedd7e5
...
...
@@ -40,12 +40,28 @@
#include <linux/slab.h>
#include "tfrc.h"
struct
tfrc_tx_hist_entry
;
/**
* tfrc_tx_hist_entry - Simple singly-linked TX history list
* @next: next oldest entry (LIFO order)
* @seqno: sequence number of this entry
* @stamp: send time of packet with sequence number @seqno
*/
struct
tfrc_tx_hist_entry
{
struct
tfrc_tx_hist_entry
*
next
;
u64
seqno
;
ktime_t
stamp
;
};
static
inline
struct
tfrc_tx_hist_entry
*
tfrc_tx_hist_find_entry
(
struct
tfrc_tx_hist_entry
*
head
,
u64
seqno
)
{
while
(
head
!=
NULL
&&
head
->
seqno
!=
seqno
)
head
=
head
->
next
;
return
head
;
}
extern
int
tfrc_tx_hist_add
(
struct
tfrc_tx_hist_entry
**
headp
,
u64
seqno
);
extern
void
tfrc_tx_hist_purge
(
struct
tfrc_tx_hist_entry
**
headp
);
extern
u32
tfrc_tx_hist_rtt
(
struct
tfrc_tx_hist_entry
*
head
,
const
u64
seqno
,
const
ktime_t
now
);
/* Subtraction a-b modulo-16, respects circular wrap-around */
#define SUB16(a, b) (((a) + 16 - (b)) & 0xF)
...
...
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