Merge master.kernel.org:/pub/scm/linux/kernel/git/acme/net-2.6
This commit is contained in:
commit
8259f16257
9 changed files with 172 additions and 123 deletions
|
@ -432,7 +432,10 @@ struct dccp_sock {
|
|||
struct ccid *dccps_hc_rx_ccid;
|
||||
struct ccid *dccps_hc_tx_ccid;
|
||||
struct dccp_options_received dccps_options_received;
|
||||
struct timeval dccps_epoch;
|
||||
enum dccp_role dccps_role:2;
|
||||
__u8 dccps_hc_rx_insert_options:1;
|
||||
__u8 dccps_hc_tx_insert_options:1;
|
||||
};
|
||||
|
||||
static inline struct dccp_sock *dccp_sk(const struct sock *sk)
|
||||
|
|
|
@ -43,12 +43,22 @@
|
|||
#include "ccid3.h"
|
||||
|
||||
/*
|
||||
* Reason for maths with 10 here is to avoid 32 bit overflow when a is big.
|
||||
* Reason for maths here is to avoid 32 bit overflow when a is big.
|
||||
* With this we get close to the limit.
|
||||
*/
|
||||
static inline u32 usecs_div(const u32 a, const u32 b)
|
||||
{
|
||||
const u32 tmp = a * (USEC_PER_SEC / 10);
|
||||
return b > 20 ? tmp / (b / 10) : tmp;
|
||||
const u32 div = a < (UINT_MAX / (USEC_PER_SEC / 10)) ? 10 :
|
||||
a < (UINT_MAX / (USEC_PER_SEC / 50)) ? 50 :
|
||||
a < (UINT_MAX / (USEC_PER_SEC / 100)) ? 100 :
|
||||
a < (UINT_MAX / (USEC_PER_SEC / 500)) ? 500 :
|
||||
a < (UINT_MAX / (USEC_PER_SEC / 1000)) ? 1000 :
|
||||
a < (UINT_MAX / (USEC_PER_SEC / 5000)) ? 5000 :
|
||||
a < (UINT_MAX / (USEC_PER_SEC / 10000)) ? 10000 :
|
||||
a < (UINT_MAX / (USEC_PER_SEC / 50000)) ? 50000 :
|
||||
100000;
|
||||
const u32 tmp = a * (USEC_PER_SEC / div);
|
||||
return (b >= 2 * div) ? tmp / (b / div) : tmp;
|
||||
}
|
||||
|
||||
static int ccid3_debug;
|
||||
|
@ -102,8 +112,7 @@ static const char *ccid3_tx_state_name(enum ccid3_hc_tx_states state)
|
|||
static inline void ccid3_hc_tx_set_state(struct sock *sk,
|
||||
enum ccid3_hc_tx_states state)
|
||||
{
|
||||
struct dccp_sock *dp = dccp_sk(sk);
|
||||
struct ccid3_hc_tx_sock *hctx = dp->dccps_hc_tx_ccid_private;
|
||||
struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);
|
||||
enum ccid3_hc_tx_states oldstate = hctx->ccid3hctx_state;
|
||||
|
||||
ccid3_pr_debug("%s(%p) %-8.8s -> %s\n",
|
||||
|
@ -144,8 +153,7 @@ static inline void ccid3_calc_new_delta(struct ccid3_hc_tx_sock *hctx)
|
|||
*/
|
||||
static void ccid3_hc_tx_update_x(struct sock *sk)
|
||||
{
|
||||
struct dccp_sock *dp = dccp_sk(sk);
|
||||
struct ccid3_hc_tx_sock *hctx = dp->dccps_hc_tx_ccid_private;
|
||||
struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);
|
||||
|
||||
/* To avoid large error in calcX */
|
||||
if (hctx->ccid3hctx_p >= TFRC_SMALLEST_P) {
|
||||
|
@ -159,7 +167,7 @@ static void ccid3_hc_tx_update_x(struct sock *sk)
|
|||
} else {
|
||||
struct timeval now;
|
||||
|
||||
do_gettimeofday(&now);
|
||||
dccp_timestamp(sk, &now);
|
||||
if (timeval_delta(&now, &hctx->ccid3hctx_t_ld) >=
|
||||
hctx->ccid3hctx_rtt) {
|
||||
hctx->ccid3hctx_x = max_t(u32, min_t(u32, hctx->ccid3hctx_x_recv,
|
||||
|
@ -174,9 +182,8 @@ static void ccid3_hc_tx_update_x(struct sock *sk)
|
|||
static void ccid3_hc_tx_no_feedback_timer(unsigned long data)
|
||||
{
|
||||
struct sock *sk = (struct sock *)data;
|
||||
struct dccp_sock *dp = dccp_sk(sk);
|
||||
unsigned long next_tmout = 0;
|
||||
struct ccid3_hc_tx_sock *hctx = dp->dccps_hc_tx_ccid_private;
|
||||
struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);
|
||||
|
||||
bh_lock_sock(sk);
|
||||
if (sock_owned_by_user(sk)) {
|
||||
|
@ -274,7 +281,7 @@ static int ccid3_hc_tx_send_packet(struct sock *sk,
|
|||
struct sk_buff *skb, int len)
|
||||
{
|
||||
struct dccp_sock *dp = dccp_sk(sk);
|
||||
struct ccid3_hc_tx_sock *hctx = dp->dccps_hc_tx_ccid_private;
|
||||
struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);
|
||||
struct dccp_tx_hist_entry *new_packet;
|
||||
struct timeval now;
|
||||
long delay;
|
||||
|
@ -307,7 +314,7 @@ static int ccid3_hc_tx_send_packet(struct sock *sk,
|
|||
dccp_tx_hist_add_entry(&hctx->ccid3hctx_hist, new_packet);
|
||||
}
|
||||
|
||||
do_gettimeofday(&now);
|
||||
dccp_timestamp(sk, &now);
|
||||
|
||||
switch (hctx->ccid3hctx_state) {
|
||||
case TFRC_SSTATE_NO_SENT:
|
||||
|
@ -348,18 +355,20 @@ static int ccid3_hc_tx_send_packet(struct sock *sk,
|
|||
}
|
||||
|
||||
/* Can we send? if so add options and add to packet history */
|
||||
if (rc == 0)
|
||||
if (rc == 0) {
|
||||
dp->dccps_hc_tx_insert_options = 1;
|
||||
new_packet->dccphtx_ccval =
|
||||
DCCP_SKB_CB(skb)->dccpd_ccval =
|
||||
hctx->ccid3hctx_last_win_count;
|
||||
}
|
||||
out:
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void ccid3_hc_tx_packet_sent(struct sock *sk, int more, int len)
|
||||
{
|
||||
struct dccp_sock *dp = dccp_sk(sk);
|
||||
struct ccid3_hc_tx_sock *hctx = dp->dccps_hc_tx_ccid_private;
|
||||
const struct dccp_sock *dp = dccp_sk(sk);
|
||||
struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);
|
||||
struct timeval now;
|
||||
|
||||
BUG_ON(hctx == NULL);
|
||||
|
@ -370,7 +379,7 @@ static void ccid3_hc_tx_packet_sent(struct sock *sk, int more, int len)
|
|||
return;
|
||||
}
|
||||
|
||||
do_gettimeofday(&now);
|
||||
dccp_timestamp(sk, &now);
|
||||
|
||||
/* check if we have sent a data packet */
|
||||
if (len > 0) {
|
||||
|
@ -445,10 +454,11 @@ static void ccid3_hc_tx_packet_sent(struct sock *sk, int more, int len)
|
|||
|
||||
static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
|
||||
{
|
||||
struct dccp_sock *dp = dccp_sk(sk);
|
||||
struct ccid3_hc_tx_sock *hctx = dp->dccps_hc_tx_ccid_private;
|
||||
const struct dccp_sock *dp = dccp_sk(sk);
|
||||
struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);
|
||||
struct ccid3_options_received *opt_recv;
|
||||
struct dccp_tx_hist_entry *packet;
|
||||
struct timeval now;
|
||||
unsigned long next_tmout;
|
||||
u32 t_elapsed;
|
||||
u32 pinv;
|
||||
|
@ -471,7 +481,7 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
|
|||
|
||||
opt_recv = &hctx->ccid3hctx_options_received;
|
||||
|
||||
t_elapsed = dp->dccps_options_received.dccpor_elapsed_time;
|
||||
t_elapsed = dp->dccps_options_received.dccpor_elapsed_time * 10;
|
||||
x_recv = opt_recv->ccid3or_receive_rate;
|
||||
pinv = opt_recv->ccid3or_loss_event_rate;
|
||||
|
||||
|
@ -496,9 +506,14 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
|
|||
}
|
||||
|
||||
/* Update RTT */
|
||||
r_sample = timeval_now_delta(&packet->dccphtx_tstamp);
|
||||
/* FIXME: */
|
||||
// r_sample -= usecs_to_jiffies(t_elapsed * 10);
|
||||
dccp_timestamp(sk, &now);
|
||||
r_sample = timeval_delta(&now, &packet->dccphtx_tstamp);
|
||||
if (unlikely(r_sample <= t_elapsed))
|
||||
LIMIT_NETDEBUG(KERN_WARNING
|
||||
"%s: r_sample=%uus, t_elapsed=%uus\n",
|
||||
__FUNCTION__, r_sample, t_elapsed);
|
||||
else
|
||||
r_sample -= t_elapsed;
|
||||
|
||||
/* Update RTT estimate by
|
||||
* If (No feedback recv)
|
||||
|
@ -591,8 +606,7 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
|
|||
|
||||
static void ccid3_hc_tx_insert_options(struct sock *sk, struct sk_buff *skb)
|
||||
{
|
||||
const struct dccp_sock *dp = dccp_sk(sk);
|
||||
struct ccid3_hc_tx_sock *hctx = dp->dccps_hc_tx_ccid_private;
|
||||
struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);
|
||||
|
||||
if (hctx == NULL || !(sk->sk_state == DCCP_OPEN ||
|
||||
sk->sk_state == DCCP_PARTOPEN))
|
||||
|
@ -606,8 +620,8 @@ static int ccid3_hc_tx_parse_options(struct sock *sk, unsigned char option,
|
|||
unsigned char *value)
|
||||
{
|
||||
int rc = 0;
|
||||
struct dccp_sock *dp = dccp_sk(sk);
|
||||
struct ccid3_hc_tx_sock *hctx = dp->dccps_hc_tx_ccid_private;
|
||||
const struct dccp_sock *dp = dccp_sk(sk);
|
||||
struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);
|
||||
struct ccid3_options_received *opt_recv;
|
||||
|
||||
if (hctx == NULL)
|
||||
|
@ -670,11 +684,11 @@ static int ccid3_hc_tx_init(struct sock *sk)
|
|||
|
||||
ccid3_pr_debug("%s, sk=%p\n", dccp_role(sk), sk);
|
||||
|
||||
hctx = dp->dccps_hc_tx_ccid_private = kmalloc(sizeof(*hctx),
|
||||
gfp_any());
|
||||
if (hctx == NULL)
|
||||
dp->dccps_hc_tx_ccid_private = kmalloc(sizeof(*hctx), gfp_any());
|
||||
if (dp->dccps_hc_tx_ccid_private == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
hctx = ccid3_hc_tx_sk(sk);
|
||||
memset(hctx, 0, sizeof(*hctx));
|
||||
|
||||
if (dp->dccps_packet_size >= TFRC_MIN_PACKET_SIZE &&
|
||||
|
@ -696,7 +710,7 @@ static int ccid3_hc_tx_init(struct sock *sk)
|
|||
static void ccid3_hc_tx_exit(struct sock *sk)
|
||||
{
|
||||
struct dccp_sock *dp = dccp_sk(sk);
|
||||
struct ccid3_hc_tx_sock *hctx = dp->dccps_hc_tx_ccid_private;
|
||||
struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);
|
||||
|
||||
ccid3_pr_debug("%s, sk=%p\n", dccp_role(sk), sk);
|
||||
BUG_ON(hctx == NULL);
|
||||
|
@ -738,8 +752,7 @@ static const char *ccid3_rx_state_name(enum ccid3_hc_rx_states state)
|
|||
static inline void ccid3_hc_rx_set_state(struct sock *sk,
|
||||
enum ccid3_hc_rx_states state)
|
||||
{
|
||||
struct dccp_sock *dp = dccp_sk(sk);
|
||||
struct ccid3_hc_rx_sock *hcrx = dp->dccps_hc_rx_ccid_private;
|
||||
struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);
|
||||
enum ccid3_hc_rx_states oldstate = hcrx->ccid3hcrx_state;
|
||||
|
||||
ccid3_pr_debug("%s(%p) %-8.8s -> %s\n",
|
||||
|
@ -751,14 +764,14 @@ static inline void ccid3_hc_rx_set_state(struct sock *sk,
|
|||
|
||||
static void ccid3_hc_rx_send_feedback(struct sock *sk)
|
||||
{
|
||||
struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);
|
||||
struct dccp_sock *dp = dccp_sk(sk);
|
||||
struct ccid3_hc_rx_sock *hcrx = dp->dccps_hc_rx_ccid_private;
|
||||
struct dccp_rx_hist_entry *packet;
|
||||
struct timeval now;
|
||||
|
||||
ccid3_pr_debug("%s, sk=%p\n", dccp_role(sk), sk);
|
||||
|
||||
do_gettimeofday(&now);
|
||||
dccp_timestamp(sk, &now);
|
||||
|
||||
switch (hcrx->ccid3hcrx_state) {
|
||||
case TFRC_RSTATE_NO_DATA:
|
||||
|
@ -767,11 +780,8 @@ static void ccid3_hc_rx_send_feedback(struct sock *sk)
|
|||
case TFRC_RSTATE_DATA: {
|
||||
const u32 delta = timeval_delta(&now,
|
||||
&hcrx->ccid3hcrx_tstamp_last_feedback);
|
||||
|
||||
hcrx->ccid3hcrx_x_recv = (hcrx->ccid3hcrx_bytes_recv *
|
||||
USEC_PER_SEC);
|
||||
if (likely(delta > 1))
|
||||
hcrx->ccid3hcrx_x_recv /= delta;
|
||||
hcrx->ccid3hcrx_x_recv = usecs_div(hcrx->ccid3hcrx_bytes_recv,
|
||||
delta);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
@ -801,14 +811,14 @@ static void ccid3_hc_rx_send_feedback(struct sock *sk)
|
|||
hcrx->ccid3hcrx_pinv = ~0;
|
||||
else
|
||||
hcrx->ccid3hcrx_pinv = 1000000 / hcrx->ccid3hcrx_p;
|
||||
dp->dccps_hc_rx_insert_options = 1;
|
||||
dccp_send_ack(sk);
|
||||
}
|
||||
|
||||
static void ccid3_hc_rx_insert_options(struct sock *sk, struct sk_buff *skb)
|
||||
{
|
||||
const struct dccp_sock *dp = dccp_sk(sk);
|
||||
struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);
|
||||
u32 x_recv, pinv;
|
||||
struct ccid3_hc_rx_sock *hcrx = dp->dccps_hc_rx_ccid_private;
|
||||
|
||||
if (hcrx == NULL || !(sk->sk_state == DCCP_OPEN ||
|
||||
sk->sk_state == DCCP_PARTOPEN))
|
||||
|
@ -837,8 +847,7 @@ static void ccid3_hc_rx_insert_options(struct sock *sk, struct sk_buff *skb)
|
|||
|
||||
static u32 ccid3_hc_rx_calc_first_li(struct sock *sk)
|
||||
{
|
||||
struct dccp_sock *dp = dccp_sk(sk);
|
||||
struct ccid3_hc_rx_sock *hcrx = dp->dccps_hc_rx_ccid_private;
|
||||
struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);
|
||||
struct dccp_rx_hist_entry *entry, *next, *tail = NULL;
|
||||
u32 rtt, delta, x_recv, fval, p, tmp2;
|
||||
struct timeval tstamp = { 0, };
|
||||
|
@ -889,10 +898,9 @@ static u32 ccid3_hc_rx_calc_first_li(struct sock *sk)
|
|||
if (rtt == 0)
|
||||
rtt = 1;
|
||||
|
||||
delta = timeval_now_delta(&hcrx->ccid3hcrx_tstamp_last_feedback);
|
||||
x_recv = hcrx->ccid3hcrx_bytes_recv * USEC_PER_SEC;
|
||||
if (likely(delta > 1))
|
||||
x_recv /= delta;
|
||||
dccp_timestamp(sk, &tstamp);
|
||||
delta = timeval_delta(&tstamp, &hcrx->ccid3hcrx_tstamp_last_feedback);
|
||||
x_recv = usecs_div(hcrx->ccid3hcrx_bytes_recv, delta);
|
||||
|
||||
tmp1 = (u64)x_recv * (u64)rtt;
|
||||
do_div(tmp1,10000000);
|
||||
|
@ -911,8 +919,7 @@ static u32 ccid3_hc_rx_calc_first_li(struct sock *sk)
|
|||
|
||||
static void ccid3_hc_rx_update_li(struct sock *sk, u64 seq_loss, u8 win_loss)
|
||||
{
|
||||
struct dccp_sock *dp = dccp_sk(sk);
|
||||
struct ccid3_hc_rx_sock *hcrx = dp->dccps_hc_rx_ccid_private;
|
||||
struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);
|
||||
|
||||
if (seq_loss != DCCP_MAX_SEQNO + 1 &&
|
||||
list_empty(&hcrx->ccid3hcrx_li_hist)) {
|
||||
|
@ -930,8 +937,7 @@ static void ccid3_hc_rx_update_li(struct sock *sk, u64 seq_loss, u8 win_loss)
|
|||
|
||||
static void ccid3_hc_rx_detect_loss(struct sock *sk)
|
||||
{
|
||||
struct dccp_sock *dp = dccp_sk(sk);
|
||||
struct ccid3_hc_rx_sock *hcrx = dp->dccps_hc_rx_ccid_private;
|
||||
struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);
|
||||
u8 win_loss;
|
||||
const u64 seq_loss = dccp_rx_hist_detect_loss(&hcrx->ccid3hcrx_hist,
|
||||
&hcrx->ccid3hcrx_li_hist,
|
||||
|
@ -942,13 +948,12 @@ static void ccid3_hc_rx_detect_loss(struct sock *sk)
|
|||
|
||||
static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb)
|
||||
{
|
||||
struct dccp_sock *dp = dccp_sk(sk);
|
||||
struct ccid3_hc_rx_sock *hcrx = dp->dccps_hc_rx_ccid_private;
|
||||
struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);
|
||||
const struct dccp_options_received *opt_recv;
|
||||
struct dccp_rx_hist_entry *packet;
|
||||
struct timeval now;
|
||||
u8 win_count;
|
||||
u32 p_prev;
|
||||
u32 p_prev, r_sample, t_elapsed;
|
||||
int ins;
|
||||
|
||||
if (hcrx == NULL)
|
||||
|
@ -957,7 +962,7 @@ static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb)
|
|||
BUG_ON(!(hcrx->ccid3hcrx_state == TFRC_RSTATE_NO_DATA ||
|
||||
hcrx->ccid3hcrx_state == TFRC_RSTATE_DATA));
|
||||
|
||||
opt_recv = &dp->dccps_options_received;
|
||||
opt_recv = &dccp_sk(sk)->dccps_options_received;
|
||||
|
||||
switch (DCCP_SKB_CB(skb)->dccpd_type) {
|
||||
case DCCP_PKT_ACK:
|
||||
|
@ -967,10 +972,24 @@ static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb)
|
|||
if (opt_recv->dccpor_timestamp_echo == 0)
|
||||
break;
|
||||
p_prev = hcrx->ccid3hcrx_rtt;
|
||||
do_gettimeofday(&now);
|
||||
hcrx->ccid3hcrx_rtt = timeval_usecs(&now) -
|
||||
(opt_recv->dccpor_timestamp_echo -
|
||||
opt_recv->dccpor_elapsed_time) * 10;
|
||||
dccp_timestamp(sk, &now);
|
||||
timeval_sub_usecs(&now, opt_recv->dccpor_timestamp_echo * 10);
|
||||
r_sample = timeval_usecs(&now);
|
||||
t_elapsed = opt_recv->dccpor_elapsed_time * 10;
|
||||
|
||||
if (unlikely(r_sample <= t_elapsed))
|
||||
LIMIT_NETDEBUG(KERN_WARNING
|
||||
"%s: r_sample=%uus, t_elapsed=%uus\n",
|
||||
__FUNCTION__, r_sample, t_elapsed);
|
||||
else
|
||||
r_sample -= t_elapsed;
|
||||
|
||||
if (hcrx->ccid3hcrx_state == TFRC_RSTATE_NO_DATA)
|
||||
hcrx->ccid3hcrx_rtt = r_sample;
|
||||
else
|
||||
hcrx->ccid3hcrx_rtt = (hcrx->ccid3hcrx_rtt * 9) / 10 +
|
||||
r_sample / 10;
|
||||
|
||||
if (p_prev != hcrx->ccid3hcrx_rtt)
|
||||
ccid3_pr_debug("%s, New RTT=%luus, elapsed time=%u\n",
|
||||
dccp_role(sk), hcrx->ccid3hcrx_rtt,
|
||||
|
@ -985,7 +1004,7 @@ static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb)
|
|||
return;
|
||||
}
|
||||
|
||||
packet = dccp_rx_hist_entry_new(ccid3_rx_hist, opt_recv->dccpor_ndp,
|
||||
packet = dccp_rx_hist_entry_new(ccid3_rx_hist, sk, opt_recv->dccpor_ndp,
|
||||
skb, SLAB_ATOMIC);
|
||||
if (packet == NULL) {
|
||||
ccid3_pr_debug("%s, sk=%p, Not enough mem to add rx packet "
|
||||
|
@ -1017,7 +1036,7 @@ static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb)
|
|||
if (ins != 0)
|
||||
break;
|
||||
|
||||
do_gettimeofday(&now);
|
||||
dccp_timestamp(sk, &now);
|
||||
if (timeval_delta(&now, &hcrx->ccid3hcrx_tstamp_last_ack) >=
|
||||
hcrx->ccid3hcrx_rtt) {
|
||||
hcrx->ccid3hcrx_tstamp_last_ack = now;
|
||||
|
@ -1056,11 +1075,11 @@ static int ccid3_hc_rx_init(struct sock *sk)
|
|||
|
||||
ccid3_pr_debug("%s, sk=%p\n", dccp_role(sk), sk);
|
||||
|
||||
hcrx = dp->dccps_hc_rx_ccid_private = kmalloc(sizeof(*hcrx),
|
||||
gfp_any());
|
||||
if (hcrx == NULL)
|
||||
dp->dccps_hc_rx_ccid_private = kmalloc(sizeof(*hcrx), gfp_any());
|
||||
if (dp->dccps_hc_rx_ccid_private == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
hcrx = ccid3_hc_rx_sk(sk);
|
||||
memset(hcrx, 0, sizeof(*hcrx));
|
||||
|
||||
if (dp->dccps_packet_size >= TFRC_MIN_PACKET_SIZE &&
|
||||
|
@ -1072,18 +1091,16 @@ static int ccid3_hc_rx_init(struct sock *sk)
|
|||
hcrx->ccid3hcrx_state = TFRC_RSTATE_NO_DATA;
|
||||
INIT_LIST_HEAD(&hcrx->ccid3hcrx_hist);
|
||||
INIT_LIST_HEAD(&hcrx->ccid3hcrx_li_hist);
|
||||
/*
|
||||
* XXX this seems to be paranoid, need to think more about this, for
|
||||
* now start with something different than zero. -acme
|
||||
*/
|
||||
hcrx->ccid3hcrx_rtt = USEC_PER_SEC / 5;
|
||||
dccp_timestamp(sk, &hcrx->ccid3hcrx_tstamp_last_ack);
|
||||
hcrx->ccid3hcrx_tstamp_last_feedback = hcrx->ccid3hcrx_tstamp_last_ack;
|
||||
hcrx->ccid3hcrx_rtt = 5000; /* XXX 5ms for now... */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ccid3_hc_rx_exit(struct sock *sk)
|
||||
{
|
||||
struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);
|
||||
struct dccp_sock *dp = dccp_sk(sk);
|
||||
struct ccid3_hc_rx_sock *hcrx = dp->dccps_hc_rx_ccid_private;
|
||||
|
||||
ccid3_pr_debug("%s, sk=%p\n", dccp_role(sk), sk);
|
||||
|
||||
|
@ -1104,8 +1121,7 @@ static void ccid3_hc_rx_exit(struct sock *sk)
|
|||
|
||||
static void ccid3_hc_rx_get_info(struct sock *sk, struct tcp_info *info)
|
||||
{
|
||||
const struct dccp_sock *dp = dccp_sk(sk);
|
||||
const struct ccid3_hc_rx_sock *hcrx = dp->dccps_hc_rx_ccid_private;
|
||||
const struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);
|
||||
|
||||
if (hcrx == NULL)
|
||||
return;
|
||||
|
@ -1117,8 +1133,7 @@ static void ccid3_hc_rx_get_info(struct sock *sk, struct tcp_info *info)
|
|||
|
||||
static void ccid3_hc_tx_get_info(struct sock *sk, struct tcp_info *info)
|
||||
{
|
||||
const struct dccp_sock *dp = dccp_sk(sk);
|
||||
const struct ccid3_hc_tx_sock *hctx = dp->dccps_hc_tx_ccid_private;
|
||||
const struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);
|
||||
|
||||
if (hctx == NULL)
|
||||
return;
|
||||
|
|
|
@ -115,7 +115,7 @@ struct ccid3_hc_rx_sock {
|
|||
u64 ccid3hcrx_seqno_last_counter:48,
|
||||
ccid3hcrx_state:8,
|
||||
ccid3hcrx_last_counter:4;
|
||||
unsigned long ccid3hcrx_rtt;
|
||||
u32 ccid3hcrx_rtt;
|
||||
u32 ccid3hcrx_p;
|
||||
u32 ccid3hcrx_bytes_recv;
|
||||
struct timeval ccid3hcrx_tstamp_last_feedback;
|
||||
|
@ -128,10 +128,14 @@ struct ccid3_hc_rx_sock {
|
|||
u32 ccid3hcrx_x_recv;
|
||||
};
|
||||
|
||||
#define ccid3_hc_tx_field(s,field) (s->dccps_hc_tx_ccid_private == NULL ? 0 : \
|
||||
((struct ccid3_hc_tx_sock *)s->dccps_hc_tx_ccid_private)->ccid3hctx_##field)
|
||||
static inline struct ccid3_hc_tx_sock *ccid3_hc_tx_sk(const struct sock *sk)
|
||||
{
|
||||
return dccp_sk(sk)->dccps_hc_tx_ccid_private;
|
||||
}
|
||||
|
||||
#define ccid3_hc_rx_field(s,field) (s->dccps_hc_rx_ccid_private == NULL ? 0 : \
|
||||
((struct ccid3_hc_rx_sock *)s->dccps_hc_rx_ccid_private)->ccid3hcrx_##field)
|
||||
static inline struct ccid3_hc_rx_sock *ccid3_hc_rx_sk(const struct sock *sk)
|
||||
{
|
||||
return dccp_sk(sk)->dccps_hc_rx_ccid_private;
|
||||
}
|
||||
|
||||
#endif /* _DCCP_CCID3_H_ */
|
||||
|
|
|
@ -134,6 +134,7 @@ static inline struct dccp_tx_hist_entry *
|
|||
|
||||
static inline struct dccp_rx_hist_entry *
|
||||
dccp_rx_hist_entry_new(struct dccp_rx_hist *hist,
|
||||
const struct sock *sk,
|
||||
const u32 ndp,
|
||||
const struct sk_buff *skb,
|
||||
const unsigned int __nocast prio)
|
||||
|
@ -148,7 +149,7 @@ static inline struct dccp_rx_hist_entry *
|
|||
entry->dccphrx_ccval = dh->dccph_ccval;
|
||||
entry->dccphrx_type = dh->dccph_type;
|
||||
entry->dccphrx_ndp = ndp;
|
||||
do_gettimeofday(&(entry->dccphrx_tstamp));
|
||||
dccp_timestamp(sk, &entry->dccphrx_tstamp);
|
||||
}
|
||||
|
||||
return entry;
|
||||
|
|
|
@ -426,10 +426,13 @@ extern struct dccp_ackpkts *
|
|||
dccp_ackpkts_alloc(unsigned int len,
|
||||
const unsigned int __nocast priority);
|
||||
extern void dccp_ackpkts_free(struct dccp_ackpkts *ap);
|
||||
extern int dccp_ackpkts_add(struct dccp_ackpkts *ap, u64 ackno, u8 state);
|
||||
extern int dccp_ackpkts_add(struct dccp_ackpkts *ap, const struct sock *sk,
|
||||
u64 ackno, u8 state);
|
||||
extern void dccp_ackpkts_check_rcv_ackno(struct dccp_ackpkts *ap,
|
||||
struct sock *sk, u64 ackno);
|
||||
|
||||
extern void dccp_timestamp(const struct sock *sk, struct timeval *tv);
|
||||
|
||||
static inline suseconds_t timeval_usecs(const struct timeval *tv)
|
||||
{
|
||||
return tv->tv_sec * USEC_PER_SEC + tv->tv_usec;
|
||||
|
@ -468,17 +471,6 @@ static inline void timeval_sub_usecs(struct timeval *tv,
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the difference in usecs between timeval
|
||||
* passed in and current time
|
||||
*/
|
||||
static inline suseconds_t timeval_now_delta(const struct timeval *tv)
|
||||
{
|
||||
struct timeval now;
|
||||
do_gettimeofday(&now);
|
||||
return timeval_delta(&now, tv);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_IP_DCCP_DEBUG
|
||||
extern void dccp_ackvector_print(const u64 ackno,
|
||||
const unsigned char *vector, int len);
|
||||
|
|
|
@ -170,7 +170,7 @@ int dccp_rcv_established(struct sock *sk, struct sk_buff *skb,
|
|||
if (dp->dccps_options.dccpo_send_ack_vector) {
|
||||
struct dccp_ackpkts *ap = dp->dccps_hc_rx_ackpkts;
|
||||
|
||||
if (dccp_ackpkts_add(dp->dccps_hc_rx_ackpkts,
|
||||
if (dccp_ackpkts_add(dp->dccps_hc_rx_ackpkts, sk,
|
||||
DCCP_SKB_CB(skb)->dccpd_seq,
|
||||
DCCP_ACKPKTS_STATE_RECEIVED)) {
|
||||
LIMIT_NETDEBUG(KERN_WARNING "DCCP: acknowledgeable "
|
||||
|
@ -498,7 +498,7 @@ int dccp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
|
|||
* DCCP_ACKPKTS_STATE_ECN_MARKED
|
||||
*/
|
||||
if (dp->dccps_options.dccpo_send_ack_vector) {
|
||||
if (dccp_ackpkts_add(dp->dccps_hc_rx_ackpkts,
|
||||
if (dccp_ackpkts_add(dp->dccps_hc_rx_ackpkts, sk,
|
||||
DCCP_SKB_CB(skb)->dccpd_seq,
|
||||
DCCP_ACKPKTS_STATE_RECEIVED))
|
||||
goto discard;
|
||||
|
|
|
@ -1243,6 +1243,7 @@ static int dccp_v4_init_sock(struct sock *sk)
|
|||
static int dccp_ctl_socket_init = 1;
|
||||
|
||||
dccp_options_init(&dp->dccps_options);
|
||||
do_gettimeofday(&dp->dccps_epoch);
|
||||
|
||||
if (dp->dccps_options.dccpo_send_ack_vector) {
|
||||
dp->dccps_hc_rx_ackpkts =
|
||||
|
|
|
@ -96,6 +96,7 @@ struct sock *dccp_create_openreq_child(struct sock *sk,
|
|||
newdp->dccps_hc_rx_ackpkts = NULL;
|
||||
newdp->dccps_role = DCCP_ROLE_SERVER;
|
||||
newicsk->icsk_rto = DCCP_TIMEOUT_INIT;
|
||||
do_gettimeofday(&newdp->dccps_epoch);
|
||||
|
||||
if (newdp->dccps_options.dccpo_send_ack_vector) {
|
||||
newdp->dccps_hc_rx_ackpkts =
|
||||
|
|
|
@ -72,6 +72,7 @@ int dccp_parse_options(struct sock *sk, struct sk_buff *skb)
|
|||
struct dccp_options_received *opt_recv = &dp->dccps_options_received;
|
||||
unsigned char opt, len;
|
||||
unsigned char *value;
|
||||
u32 elapsed_time;
|
||||
|
||||
memset(opt_recv, 0, sizeof(*opt_recv));
|
||||
|
||||
|
@ -139,7 +140,7 @@ int dccp_parse_options(struct sock *sk, struct sk_buff *skb)
|
|||
opt_recv->dccpor_timestamp = ntohl(*(u32 *)value);
|
||||
|
||||
dp->dccps_timestamp_echo = opt_recv->dccpor_timestamp;
|
||||
do_gettimeofday(&dp->dccps_timestamp_time);
|
||||
dccp_timestamp(sk, &dp->dccps_timestamp_time);
|
||||
|
||||
dccp_pr_debug("%sTIMESTAMP=%u, ackno=%llu\n",
|
||||
debug_prefix, opt_recv->dccpor_timestamp,
|
||||
|
@ -159,18 +160,18 @@ int dccp_parse_options(struct sock *sk, struct sk_buff *skb)
|
|||
(unsigned long long)
|
||||
DCCP_SKB_CB(skb)->dccpd_ack_seq);
|
||||
|
||||
if (len > 4) {
|
||||
if (len == 6)
|
||||
opt_recv->dccpor_elapsed_time =
|
||||
ntohs(*(u16 *)(value + 4));
|
||||
else
|
||||
opt_recv->dccpor_elapsed_time =
|
||||
ntohl(*(u32 *)(value + 4));
|
||||
|
||||
dccp_pr_debug("%sTIMESTAMP_ECHO ELAPSED_TIME=%d\n",
|
||||
debug_prefix,
|
||||
opt_recv->dccpor_elapsed_time);
|
||||
}
|
||||
if (len == 4)
|
||||
break;
|
||||
|
||||
if (len == 6)
|
||||
elapsed_time = ntohs(*(u16 *)(value + 4));
|
||||
else
|
||||
elapsed_time = ntohl(*(u32 *)(value + 4));
|
||||
|
||||
/* Give precedence to the biggest ELAPSED_TIME */
|
||||
if (elapsed_time > opt_recv->dccpor_elapsed_time)
|
||||
opt_recv->dccpor_elapsed_time = elapsed_time;
|
||||
break;
|
||||
case DCCPO_ELAPSED_TIME:
|
||||
if (len != 2 && len != 4)
|
||||
|
@ -180,14 +181,15 @@ int dccp_parse_options(struct sock *sk, struct sk_buff *skb)
|
|||
continue;
|
||||
|
||||
if (len == 2)
|
||||
opt_recv->dccpor_elapsed_time =
|
||||
ntohs(*(u16 *)value);
|
||||
elapsed_time = ntohs(*(u16 *)value);
|
||||
else
|
||||
opt_recv->dccpor_elapsed_time =
|
||||
ntohl(*(u32 *)value);
|
||||
elapsed_time = ntohl(*(u32 *)value);
|
||||
|
||||
if (elapsed_time > opt_recv->dccpor_elapsed_time)
|
||||
opt_recv->dccpor_elapsed_time = elapsed_time;
|
||||
|
||||
dccp_pr_debug("%sELAPSED_TIME=%d\n", debug_prefix,
|
||||
opt_recv->dccpor_elapsed_time);
|
||||
elapsed_time);
|
||||
break;
|
||||
/*
|
||||
* From draft-ietf-dccp-spec-11.txt:
|
||||
|
@ -359,9 +361,13 @@ static void dccp_insert_option_ack_vector(struct sock *sk, struct sk_buff *skb)
|
|||
#endif
|
||||
struct dccp_ackpkts *ap = dp->dccps_hc_rx_ackpkts;
|
||||
int len = ap->dccpap_buf_vector_len + 2;
|
||||
const u32 elapsed_time = timeval_now_delta(&ap->dccpap_time) / 10;
|
||||
struct timeval now;
|
||||
u32 elapsed_time;
|
||||
unsigned char *to, *from;
|
||||
|
||||
dccp_timestamp(sk, &now);
|
||||
elapsed_time = timeval_delta(&now, &ap->dccpap_time) / 10;
|
||||
|
||||
if (elapsed_time != 0)
|
||||
dccp_insert_option_elapsed_time(sk, skb, elapsed_time);
|
||||
|
||||
|
@ -426,13 +432,29 @@ static void dccp_insert_option_ack_vector(struct sock *sk, struct sk_buff *skb)
|
|||
(unsigned long long) ap->dccpap_ack_ackno);
|
||||
}
|
||||
|
||||
void dccp_timestamp(const struct sock *sk, struct timeval *tv)
|
||||
{
|
||||
const struct dccp_sock *dp = dccp_sk(sk);
|
||||
|
||||
do_gettimeofday(tv);
|
||||
tv->tv_sec -= dp->dccps_epoch.tv_sec;
|
||||
tv->tv_usec -= dp->dccps_epoch.tv_usec;
|
||||
|
||||
while (tv->tv_usec < 0) {
|
||||
tv->tv_sec--;
|
||||
tv->tv_usec += USEC_PER_SEC;
|
||||
}
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL_GPL(dccp_timestamp);
|
||||
|
||||
void dccp_insert_option_timestamp(struct sock *sk, struct sk_buff *skb)
|
||||
{
|
||||
struct timeval tv;
|
||||
u32 now;
|
||||
|
||||
do_gettimeofday(&tv);
|
||||
now = (tv.tv_sec * USEC_PER_SEC + tv.tv_usec) / 10;
|
||||
dccp_timestamp(sk, &tv);
|
||||
now = timeval_usecs(&tv) / 10;
|
||||
/* yes this will overflow but that is the point as we want a
|
||||
* 10 usec 32 bit timer which mean it wraps every 11.9 hours */
|
||||
|
||||
|
@ -450,13 +472,17 @@ static void dccp_insert_option_timestamp_echo(struct sock *sk,
|
|||
const char *debug_prefix = dp->dccps_role == DCCP_ROLE_CLIENT ?
|
||||
"CLIENT TX opt: " : "server TX opt: ";
|
||||
#endif
|
||||
struct timeval now;
|
||||
u32 tstamp_echo;
|
||||
const u32 elapsed_time =
|
||||
timeval_now_delta(&dp->dccps_timestamp_time) / 10;
|
||||
const int elapsed_time_len = dccp_elapsed_time_len(elapsed_time);
|
||||
const int len = 6 + elapsed_time_len;
|
||||
u32 elapsed_time;
|
||||
int len, elapsed_time_len;
|
||||
unsigned char *to;
|
||||
|
||||
dccp_timestamp(sk, &now);
|
||||
elapsed_time = timeval_delta(&now, &dp->dccps_timestamp_time) / 10;
|
||||
elapsed_time_len = dccp_elapsed_time_len(elapsed_time);
|
||||
len = 6 + elapsed_time_len;
|
||||
|
||||
if (DCCP_SKB_CB(skb)->dccpd_opt_len + len > DCCP_MAX_OPT_LEN) {
|
||||
LIMIT_NETDEBUG(KERN_INFO "DCCP: packet too small to insert "
|
||||
"timestamp echo!\n");
|
||||
|
@ -505,13 +531,18 @@ void dccp_insert_options(struct sock *sk, struct sk_buff *skb)
|
|||
(dp->dccps_hc_rx_ackpkts->dccpap_buf_ackno !=
|
||||
DCCP_MAX_SEQNO + 1))
|
||||
dccp_insert_option_ack_vector(sk, skb);
|
||||
|
||||
if (dp->dccps_timestamp_echo != 0)
|
||||
dccp_insert_option_timestamp_echo(sk, skb);
|
||||
}
|
||||
|
||||
ccid_hc_rx_insert_options(dp->dccps_hc_rx_ccid, sk, skb);
|
||||
ccid_hc_tx_insert_options(dp->dccps_hc_tx_ccid, sk, skb);
|
||||
if (dp->dccps_hc_rx_insert_options) {
|
||||
ccid_hc_rx_insert_options(dp->dccps_hc_rx_ccid, sk, skb);
|
||||
dp->dccps_hc_rx_insert_options = 0;
|
||||
}
|
||||
if (dp->dccps_hc_tx_insert_options) {
|
||||
ccid_hc_tx_insert_options(dp->dccps_hc_tx_ccid, sk, skb);
|
||||
dp->dccps_hc_tx_insert_options = 0;
|
||||
}
|
||||
|
||||
/* XXX: insert other options when appropriate */
|
||||
|
||||
|
@ -616,7 +647,8 @@ static inline int dccp_ackpkts_set_buf_head_state(struct dccp_ackpkts *ap,
|
|||
/*
|
||||
* Implements the draft-ietf-dccp-spec-11.txt Appendix A
|
||||
*/
|
||||
int dccp_ackpkts_add(struct dccp_ackpkts *ap, u64 ackno, u8 state)
|
||||
int dccp_ackpkts_add(struct dccp_ackpkts *ap, const struct sock *sk,
|
||||
u64 ackno, u8 state)
|
||||
{
|
||||
/*
|
||||
* Check at the right places if the buffer is full, if it is, tell the
|
||||
|
@ -697,7 +729,7 @@ int dccp_ackpkts_add(struct dccp_ackpkts *ap, u64 ackno, u8 state)
|
|||
}
|
||||
|
||||
ap->dccpap_buf_ackno = ackno;
|
||||
do_gettimeofday(&ap->dccpap_time);
|
||||
dccp_timestamp(sk, &ap->dccpap_time);
|
||||
out:
|
||||
dccp_pr_debug("");
|
||||
dccp_ackpkts_print(ap);
|
||||
|
|
Loading…
Reference in a new issue