Merge master.kernel.org:/pub/scm/linux/kernel/git/acme/net-2.6

This commit is contained in:
David S. Miller 2005-09-09 13:17:43 -07:00
Родитель 5dce225bd9 59725dc2a2
Коммит 8259f16257
9 изменённых файлов: 172 добавлений и 123 удалений

Просмотреть файл

@ -432,7 +432,10 @@ struct dccp_sock {
struct ccid *dccps_hc_rx_ccid; struct ccid *dccps_hc_rx_ccid;
struct ccid *dccps_hc_tx_ccid; struct ccid *dccps_hc_tx_ccid;
struct dccp_options_received dccps_options_received; struct dccp_options_received dccps_options_received;
struct timeval dccps_epoch;
enum dccp_role dccps_role:2; 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) static inline struct dccp_sock *dccp_sk(const struct sock *sk)

Просмотреть файл

@ -43,12 +43,22 @@
#include "ccid3.h" #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) static inline u32 usecs_div(const u32 a, const u32 b)
{ {
const u32 tmp = a * (USEC_PER_SEC / 10); const u32 div = a < (UINT_MAX / (USEC_PER_SEC / 10)) ? 10 :
return b > 20 ? tmp / (b / 10) : tmp; 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; 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, static inline void ccid3_hc_tx_set_state(struct sock *sk,
enum ccid3_hc_tx_states state) enum ccid3_hc_tx_states state)
{ {
struct dccp_sock *dp = dccp_sk(sk); struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);
struct ccid3_hc_tx_sock *hctx = dp->dccps_hc_tx_ccid_private;
enum ccid3_hc_tx_states oldstate = hctx->ccid3hctx_state; enum ccid3_hc_tx_states oldstate = hctx->ccid3hctx_state;
ccid3_pr_debug("%s(%p) %-8.8s -> %s\n", 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) static void ccid3_hc_tx_update_x(struct sock *sk)
{ {
struct dccp_sock *dp = dccp_sk(sk); struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);
struct ccid3_hc_tx_sock *hctx = dp->dccps_hc_tx_ccid_private;
/* To avoid large error in calcX */ /* To avoid large error in calcX */
if (hctx->ccid3hctx_p >= TFRC_SMALLEST_P) { if (hctx->ccid3hctx_p >= TFRC_SMALLEST_P) {
@ -159,7 +167,7 @@ static void ccid3_hc_tx_update_x(struct sock *sk)
} else { } else {
struct timeval now; struct timeval now;
do_gettimeofday(&now); dccp_timestamp(sk, &now);
if (timeval_delta(&now, &hctx->ccid3hctx_t_ld) >= if (timeval_delta(&now, &hctx->ccid3hctx_t_ld) >=
hctx->ccid3hctx_rtt) { hctx->ccid3hctx_rtt) {
hctx->ccid3hctx_x = max_t(u32, min_t(u32, hctx->ccid3hctx_x_recv, 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) static void ccid3_hc_tx_no_feedback_timer(unsigned long data)
{ {
struct sock *sk = (struct sock *)data; struct sock *sk = (struct sock *)data;
struct dccp_sock *dp = dccp_sk(sk);
unsigned long next_tmout = 0; 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); bh_lock_sock(sk);
if (sock_owned_by_user(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 sk_buff *skb, int len)
{ {
struct dccp_sock *dp = dccp_sk(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);
struct dccp_tx_hist_entry *new_packet; struct dccp_tx_hist_entry *new_packet;
struct timeval now; struct timeval now;
long delay; 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); dccp_tx_hist_add_entry(&hctx->ccid3hctx_hist, new_packet);
} }
do_gettimeofday(&now); dccp_timestamp(sk, &now);
switch (hctx->ccid3hctx_state) { switch (hctx->ccid3hctx_state) {
case TFRC_SSTATE_NO_SENT: 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 */ /* 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 = new_packet->dccphtx_ccval =
DCCP_SKB_CB(skb)->dccpd_ccval = DCCP_SKB_CB(skb)->dccpd_ccval =
hctx->ccid3hctx_last_win_count; hctx->ccid3hctx_last_win_count;
}
out: out:
return rc; return rc;
} }
static void ccid3_hc_tx_packet_sent(struct sock *sk, int more, int len) static void ccid3_hc_tx_packet_sent(struct sock *sk, int more, int len)
{ {
struct dccp_sock *dp = dccp_sk(sk); 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);
struct timeval now; struct timeval now;
BUG_ON(hctx == NULL); BUG_ON(hctx == NULL);
@ -370,7 +379,7 @@ static void ccid3_hc_tx_packet_sent(struct sock *sk, int more, int len)
return; return;
} }
do_gettimeofday(&now); dccp_timestamp(sk, &now);
/* check if we have sent a data packet */ /* check if we have sent a data packet */
if (len > 0) { 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) static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
{ {
struct dccp_sock *dp = dccp_sk(sk); 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);
struct ccid3_options_received *opt_recv; struct ccid3_options_received *opt_recv;
struct dccp_tx_hist_entry *packet; struct dccp_tx_hist_entry *packet;
struct timeval now;
unsigned long next_tmout; unsigned long next_tmout;
u32 t_elapsed; u32 t_elapsed;
u32 pinv; 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; 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; x_recv = opt_recv->ccid3or_receive_rate;
pinv = opt_recv->ccid3or_loss_event_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 */ /* Update RTT */
r_sample = timeval_now_delta(&packet->dccphtx_tstamp); dccp_timestamp(sk, &now);
/* FIXME: */ r_sample = timeval_delta(&now, &packet->dccphtx_tstamp);
// r_sample -= usecs_to_jiffies(t_elapsed * 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;
/* Update RTT estimate by /* Update RTT estimate by
* If (No feedback recv) * 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) 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 = ccid3_hc_tx_sk(sk);
struct ccid3_hc_tx_sock *hctx = dp->dccps_hc_tx_ccid_private;
if (hctx == NULL || !(sk->sk_state == DCCP_OPEN || if (hctx == NULL || !(sk->sk_state == DCCP_OPEN ||
sk->sk_state == DCCP_PARTOPEN)) 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) unsigned char *value)
{ {
int rc = 0; int rc = 0;
struct dccp_sock *dp = dccp_sk(sk); 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);
struct ccid3_options_received *opt_recv; struct ccid3_options_received *opt_recv;
if (hctx == NULL) 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); ccid3_pr_debug("%s, sk=%p\n", dccp_role(sk), sk);
hctx = dp->dccps_hc_tx_ccid_private = kmalloc(sizeof(*hctx), dp->dccps_hc_tx_ccid_private = kmalloc(sizeof(*hctx), gfp_any());
gfp_any()); if (dp->dccps_hc_tx_ccid_private == NULL)
if (hctx == NULL)
return -ENOMEM; return -ENOMEM;
hctx = ccid3_hc_tx_sk(sk);
memset(hctx, 0, sizeof(*hctx)); memset(hctx, 0, sizeof(*hctx));
if (dp->dccps_packet_size >= TFRC_MIN_PACKET_SIZE && 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) static void ccid3_hc_tx_exit(struct sock *sk)
{ {
struct dccp_sock *dp = dccp_sk(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); ccid3_pr_debug("%s, sk=%p\n", dccp_role(sk), sk);
BUG_ON(hctx == NULL); 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, static inline void ccid3_hc_rx_set_state(struct sock *sk,
enum ccid3_hc_rx_states state) enum ccid3_hc_rx_states state)
{ {
struct dccp_sock *dp = dccp_sk(sk); struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);
struct ccid3_hc_rx_sock *hcrx = dp->dccps_hc_rx_ccid_private;
enum ccid3_hc_rx_states oldstate = hcrx->ccid3hcrx_state; enum ccid3_hc_rx_states oldstate = hcrx->ccid3hcrx_state;
ccid3_pr_debug("%s(%p) %-8.8s -> %s\n", 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) 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 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 dccp_rx_hist_entry *packet;
struct timeval now; struct timeval now;
ccid3_pr_debug("%s, sk=%p\n", dccp_role(sk), sk); ccid3_pr_debug("%s, sk=%p\n", dccp_role(sk), sk);
do_gettimeofday(&now); dccp_timestamp(sk, &now);
switch (hcrx->ccid3hcrx_state) { switch (hcrx->ccid3hcrx_state) {
case TFRC_RSTATE_NO_DATA: case TFRC_RSTATE_NO_DATA:
@ -767,11 +780,8 @@ static void ccid3_hc_rx_send_feedback(struct sock *sk)
case TFRC_RSTATE_DATA: { case TFRC_RSTATE_DATA: {
const u32 delta = timeval_delta(&now, const u32 delta = timeval_delta(&now,
&hcrx->ccid3hcrx_tstamp_last_feedback); &hcrx->ccid3hcrx_tstamp_last_feedback);
hcrx->ccid3hcrx_x_recv = usecs_div(hcrx->ccid3hcrx_bytes_recv,
hcrx->ccid3hcrx_x_recv = (hcrx->ccid3hcrx_bytes_recv * delta);
USEC_PER_SEC);
if (likely(delta > 1))
hcrx->ccid3hcrx_x_recv /= delta;
} }
break; break;
default: default:
@ -801,14 +811,14 @@ static void ccid3_hc_rx_send_feedback(struct sock *sk)
hcrx->ccid3hcrx_pinv = ~0; hcrx->ccid3hcrx_pinv = ~0;
else else
hcrx->ccid3hcrx_pinv = 1000000 / hcrx->ccid3hcrx_p; hcrx->ccid3hcrx_pinv = 1000000 / hcrx->ccid3hcrx_p;
dp->dccps_hc_rx_insert_options = 1;
dccp_send_ack(sk); dccp_send_ack(sk);
} }
static void ccid3_hc_rx_insert_options(struct sock *sk, struct sk_buff *skb) 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; u32 x_recv, pinv;
struct ccid3_hc_rx_sock *hcrx = dp->dccps_hc_rx_ccid_private;
if (hcrx == NULL || !(sk->sk_state == DCCP_OPEN || if (hcrx == NULL || !(sk->sk_state == DCCP_OPEN ||
sk->sk_state == DCCP_PARTOPEN)) 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) static u32 ccid3_hc_rx_calc_first_li(struct sock *sk)
{ {
struct dccp_sock *dp = dccp_sk(sk); struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);
struct ccid3_hc_rx_sock *hcrx = dp->dccps_hc_rx_ccid_private;
struct dccp_rx_hist_entry *entry, *next, *tail = NULL; struct dccp_rx_hist_entry *entry, *next, *tail = NULL;
u32 rtt, delta, x_recv, fval, p, tmp2; u32 rtt, delta, x_recv, fval, p, tmp2;
struct timeval tstamp = { 0, }; struct timeval tstamp = { 0, };
@ -889,10 +898,9 @@ found:
if (rtt == 0) if (rtt == 0)
rtt = 1; rtt = 1;
delta = timeval_now_delta(&hcrx->ccid3hcrx_tstamp_last_feedback); dccp_timestamp(sk, &tstamp);
x_recv = hcrx->ccid3hcrx_bytes_recv * USEC_PER_SEC; delta = timeval_delta(&tstamp, &hcrx->ccid3hcrx_tstamp_last_feedback);
if (likely(delta > 1)) x_recv = usecs_div(hcrx->ccid3hcrx_bytes_recv, delta);
x_recv /= delta;
tmp1 = (u64)x_recv * (u64)rtt; tmp1 = (u64)x_recv * (u64)rtt;
do_div(tmp1,10000000); do_div(tmp1,10000000);
@ -911,8 +919,7 @@ found:
static void ccid3_hc_rx_update_li(struct sock *sk, u64 seq_loss, u8 win_loss) 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 = ccid3_hc_rx_sk(sk);
struct ccid3_hc_rx_sock *hcrx = dp->dccps_hc_rx_ccid_private;
if (seq_loss != DCCP_MAX_SEQNO + 1 && if (seq_loss != DCCP_MAX_SEQNO + 1 &&
list_empty(&hcrx->ccid3hcrx_li_hist)) { 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) static void ccid3_hc_rx_detect_loss(struct sock *sk)
{ {
struct dccp_sock *dp = dccp_sk(sk); struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);
struct ccid3_hc_rx_sock *hcrx = dp->dccps_hc_rx_ccid_private;
u8 win_loss; u8 win_loss;
const u64 seq_loss = dccp_rx_hist_detect_loss(&hcrx->ccid3hcrx_hist, const u64 seq_loss = dccp_rx_hist_detect_loss(&hcrx->ccid3hcrx_hist,
&hcrx->ccid3hcrx_li_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) 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 = ccid3_hc_rx_sk(sk);
struct ccid3_hc_rx_sock *hcrx = dp->dccps_hc_rx_ccid_private;
const struct dccp_options_received *opt_recv; const struct dccp_options_received *opt_recv;
struct dccp_rx_hist_entry *packet; struct dccp_rx_hist_entry *packet;
struct timeval now; struct timeval now;
u8 win_count; u8 win_count;
u32 p_prev; u32 p_prev, r_sample, t_elapsed;
int ins; int ins;
if (hcrx == NULL) 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 || BUG_ON(!(hcrx->ccid3hcrx_state == TFRC_RSTATE_NO_DATA ||
hcrx->ccid3hcrx_state == TFRC_RSTATE_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) { switch (DCCP_SKB_CB(skb)->dccpd_type) {
case DCCP_PKT_ACK: 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) if (opt_recv->dccpor_timestamp_echo == 0)
break; break;
p_prev = hcrx->ccid3hcrx_rtt; p_prev = hcrx->ccid3hcrx_rtt;
do_gettimeofday(&now); dccp_timestamp(sk, &now);
hcrx->ccid3hcrx_rtt = timeval_usecs(&now) - timeval_sub_usecs(&now, opt_recv->dccpor_timestamp_echo * 10);
(opt_recv->dccpor_timestamp_echo - r_sample = timeval_usecs(&now);
opt_recv->dccpor_elapsed_time) * 10; 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) if (p_prev != hcrx->ccid3hcrx_rtt)
ccid3_pr_debug("%s, New RTT=%luus, elapsed time=%u\n", ccid3_pr_debug("%s, New RTT=%luus, elapsed time=%u\n",
dccp_role(sk), hcrx->ccid3hcrx_rtt, 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; 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); skb, SLAB_ATOMIC);
if (packet == NULL) { if (packet == NULL) {
ccid3_pr_debug("%s, sk=%p, Not enough mem to add rx packet " 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) if (ins != 0)
break; break;
do_gettimeofday(&now); dccp_timestamp(sk, &now);
if (timeval_delta(&now, &hcrx->ccid3hcrx_tstamp_last_ack) >= if (timeval_delta(&now, &hcrx->ccid3hcrx_tstamp_last_ack) >=
hcrx->ccid3hcrx_rtt) { hcrx->ccid3hcrx_rtt) {
hcrx->ccid3hcrx_tstamp_last_ack = now; 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); ccid3_pr_debug("%s, sk=%p\n", dccp_role(sk), sk);
hcrx = dp->dccps_hc_rx_ccid_private = kmalloc(sizeof(*hcrx), dp->dccps_hc_rx_ccid_private = kmalloc(sizeof(*hcrx), gfp_any());
gfp_any()); if (dp->dccps_hc_rx_ccid_private == NULL)
if (hcrx == NULL)
return -ENOMEM; return -ENOMEM;
hcrx = ccid3_hc_rx_sk(sk);
memset(hcrx, 0, sizeof(*hcrx)); memset(hcrx, 0, sizeof(*hcrx));
if (dp->dccps_packet_size >= TFRC_MIN_PACKET_SIZE && 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; hcrx->ccid3hcrx_state = TFRC_RSTATE_NO_DATA;
INIT_LIST_HEAD(&hcrx->ccid3hcrx_hist); INIT_LIST_HEAD(&hcrx->ccid3hcrx_hist);
INIT_LIST_HEAD(&hcrx->ccid3hcrx_li_hist); INIT_LIST_HEAD(&hcrx->ccid3hcrx_li_hist);
/* dccp_timestamp(sk, &hcrx->ccid3hcrx_tstamp_last_ack);
* XXX this seems to be paranoid, need to think more about this, for hcrx->ccid3hcrx_tstamp_last_feedback = hcrx->ccid3hcrx_tstamp_last_ack;
* now start with something different than zero. -acme hcrx->ccid3hcrx_rtt = 5000; /* XXX 5ms for now... */
*/
hcrx->ccid3hcrx_rtt = USEC_PER_SEC / 5;
return 0; return 0;
} }
static void ccid3_hc_rx_exit(struct sock *sk) 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 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); 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) 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 = ccid3_hc_rx_sk(sk);
const struct ccid3_hc_rx_sock *hcrx = dp->dccps_hc_rx_ccid_private;
if (hcrx == NULL) if (hcrx == NULL)
return; 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) 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 = ccid3_hc_tx_sk(sk);
const struct ccid3_hc_tx_sock *hctx = dp->dccps_hc_tx_ccid_private;
if (hctx == NULL) if (hctx == NULL)
return; return;

Просмотреть файл

@ -115,7 +115,7 @@ struct ccid3_hc_rx_sock {
u64 ccid3hcrx_seqno_last_counter:48, u64 ccid3hcrx_seqno_last_counter:48,
ccid3hcrx_state:8, ccid3hcrx_state:8,
ccid3hcrx_last_counter:4; ccid3hcrx_last_counter:4;
unsigned long ccid3hcrx_rtt; u32 ccid3hcrx_rtt;
u32 ccid3hcrx_p; u32 ccid3hcrx_p;
u32 ccid3hcrx_bytes_recv; u32 ccid3hcrx_bytes_recv;
struct timeval ccid3hcrx_tstamp_last_feedback; struct timeval ccid3hcrx_tstamp_last_feedback;
@ -128,10 +128,14 @@ struct ccid3_hc_rx_sock {
u32 ccid3hcrx_x_recv; u32 ccid3hcrx_x_recv;
}; };
#define ccid3_hc_tx_field(s,field) (s->dccps_hc_tx_ccid_private == NULL ? 0 : \ static inline struct ccid3_hc_tx_sock *ccid3_hc_tx_sk(const struct sock *sk)
((struct ccid3_hc_tx_sock *)s->dccps_hc_tx_ccid_private)->ccid3hctx_##field) {
return dccp_sk(sk)->dccps_hc_tx_ccid_private;
}
#define ccid3_hc_rx_field(s,field) (s->dccps_hc_rx_ccid_private == NULL ? 0 : \ static inline struct ccid3_hc_rx_sock *ccid3_hc_rx_sk(const struct sock *sk)
((struct ccid3_hc_rx_sock *)s->dccps_hc_rx_ccid_private)->ccid3hcrx_##field) {
return dccp_sk(sk)->dccps_hc_rx_ccid_private;
}
#endif /* _DCCP_CCID3_H_ */ #endif /* _DCCP_CCID3_H_ */

Просмотреть файл

@ -134,6 +134,7 @@ static inline struct dccp_tx_hist_entry *
static inline struct dccp_rx_hist_entry * static inline struct dccp_rx_hist_entry *
dccp_rx_hist_entry_new(struct dccp_rx_hist *hist, dccp_rx_hist_entry_new(struct dccp_rx_hist *hist,
const struct sock *sk,
const u32 ndp, const u32 ndp,
const struct sk_buff *skb, const struct sk_buff *skb,
const unsigned int __nocast prio) const unsigned int __nocast prio)
@ -148,7 +149,7 @@ static inline struct dccp_rx_hist_entry *
entry->dccphrx_ccval = dh->dccph_ccval; entry->dccphrx_ccval = dh->dccph_ccval;
entry->dccphrx_type = dh->dccph_type; entry->dccphrx_type = dh->dccph_type;
entry->dccphrx_ndp = ndp; entry->dccphrx_ndp = ndp;
do_gettimeofday(&(entry->dccphrx_tstamp)); dccp_timestamp(sk, &entry->dccphrx_tstamp);
} }
return entry; return entry;

Просмотреть файл

@ -426,10 +426,13 @@ extern struct dccp_ackpkts *
dccp_ackpkts_alloc(unsigned int len, dccp_ackpkts_alloc(unsigned int len,
const unsigned int __nocast priority); const unsigned int __nocast priority);
extern void dccp_ackpkts_free(struct dccp_ackpkts *ap); 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, extern void dccp_ackpkts_check_rcv_ackno(struct dccp_ackpkts *ap,
struct sock *sk, u64 ackno); 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) static inline suseconds_t timeval_usecs(const struct timeval *tv)
{ {
return tv->tv_sec * USEC_PER_SEC + tv->tv_usec; 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 #ifdef CONFIG_IP_DCCP_DEBUG
extern void dccp_ackvector_print(const u64 ackno, extern void dccp_ackvector_print(const u64 ackno,
const unsigned char *vector, int len); 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) { if (dp->dccps_options.dccpo_send_ack_vector) {
struct dccp_ackpkts *ap = dp->dccps_hc_rx_ackpkts; 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_SKB_CB(skb)->dccpd_seq,
DCCP_ACKPKTS_STATE_RECEIVED)) { DCCP_ACKPKTS_STATE_RECEIVED)) {
LIMIT_NETDEBUG(KERN_WARNING "DCCP: acknowledgeable " 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 * DCCP_ACKPKTS_STATE_ECN_MARKED
*/ */
if (dp->dccps_options.dccpo_send_ack_vector) { 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_SKB_CB(skb)->dccpd_seq,
DCCP_ACKPKTS_STATE_RECEIVED)) DCCP_ACKPKTS_STATE_RECEIVED))
goto discard; goto discard;

Просмотреть файл

@ -1243,6 +1243,7 @@ static int dccp_v4_init_sock(struct sock *sk)
static int dccp_ctl_socket_init = 1; static int dccp_ctl_socket_init = 1;
dccp_options_init(&dp->dccps_options); dccp_options_init(&dp->dccps_options);
do_gettimeofday(&dp->dccps_epoch);
if (dp->dccps_options.dccpo_send_ack_vector) { if (dp->dccps_options.dccpo_send_ack_vector) {
dp->dccps_hc_rx_ackpkts = 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_hc_rx_ackpkts = NULL;
newdp->dccps_role = DCCP_ROLE_SERVER; newdp->dccps_role = DCCP_ROLE_SERVER;
newicsk->icsk_rto = DCCP_TIMEOUT_INIT; newicsk->icsk_rto = DCCP_TIMEOUT_INIT;
do_gettimeofday(&newdp->dccps_epoch);
if (newdp->dccps_options.dccpo_send_ack_vector) { if (newdp->dccps_options.dccpo_send_ack_vector) {
newdp->dccps_hc_rx_ackpkts = 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; struct dccp_options_received *opt_recv = &dp->dccps_options_received;
unsigned char opt, len; unsigned char opt, len;
unsigned char *value; unsigned char *value;
u32 elapsed_time;
memset(opt_recv, 0, sizeof(*opt_recv)); 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); opt_recv->dccpor_timestamp = ntohl(*(u32 *)value);
dp->dccps_timestamp_echo = opt_recv->dccpor_timestamp; 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", dccp_pr_debug("%sTIMESTAMP=%u, ackno=%llu\n",
debug_prefix, opt_recv->dccpor_timestamp, debug_prefix, opt_recv->dccpor_timestamp,
@ -159,18 +160,18 @@ int dccp_parse_options(struct sock *sk, struct sk_buff *skb)
(unsigned long long) (unsigned long long)
DCCP_SKB_CB(skb)->dccpd_ack_seq); 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", if (len == 4)
debug_prefix, break;
opt_recv->dccpor_elapsed_time);
} 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; break;
case DCCPO_ELAPSED_TIME: case DCCPO_ELAPSED_TIME:
if (len != 2 && len != 4) if (len != 2 && len != 4)
@ -180,14 +181,15 @@ int dccp_parse_options(struct sock *sk, struct sk_buff *skb)
continue; continue;
if (len == 2) if (len == 2)
opt_recv->dccpor_elapsed_time = elapsed_time = ntohs(*(u16 *)value);
ntohs(*(u16 *)value);
else else
opt_recv->dccpor_elapsed_time = elapsed_time = ntohl(*(u32 *)value);
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, dccp_pr_debug("%sELAPSED_TIME=%d\n", debug_prefix,
opt_recv->dccpor_elapsed_time); elapsed_time);
break; break;
/* /*
* From draft-ietf-dccp-spec-11.txt: * 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 #endif
struct dccp_ackpkts *ap = dp->dccps_hc_rx_ackpkts; struct dccp_ackpkts *ap = dp->dccps_hc_rx_ackpkts;
int len = ap->dccpap_buf_vector_len + 2; 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; unsigned char *to, *from;
dccp_timestamp(sk, &now);
elapsed_time = timeval_delta(&now, &ap->dccpap_time) / 10;
if (elapsed_time != 0) if (elapsed_time != 0)
dccp_insert_option_elapsed_time(sk, skb, elapsed_time); 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); (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) void dccp_insert_option_timestamp(struct sock *sk, struct sk_buff *skb)
{ {
struct timeval tv; struct timeval tv;
u32 now; u32 now;
do_gettimeofday(&tv); dccp_timestamp(sk, &tv);
now = (tv.tv_sec * USEC_PER_SEC + tv.tv_usec) / 10; now = timeval_usecs(&tv) / 10;
/* yes this will overflow but that is the point as we want a /* 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 */ * 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 ? const char *debug_prefix = dp->dccps_role == DCCP_ROLE_CLIENT ?
"CLIENT TX opt: " : "server TX opt: "; "CLIENT TX opt: " : "server TX opt: ";
#endif #endif
struct timeval now;
u32 tstamp_echo; u32 tstamp_echo;
const u32 elapsed_time = u32 elapsed_time;
timeval_now_delta(&dp->dccps_timestamp_time) / 10; int len, elapsed_time_len;
const int elapsed_time_len = dccp_elapsed_time_len(elapsed_time);
const int len = 6 + elapsed_time_len;
unsigned char *to; 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) { if (DCCP_SKB_CB(skb)->dccpd_opt_len + len > DCCP_MAX_OPT_LEN) {
LIMIT_NETDEBUG(KERN_INFO "DCCP: packet too small to insert " LIMIT_NETDEBUG(KERN_INFO "DCCP: packet too small to insert "
"timestamp echo!\n"); "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 != (dp->dccps_hc_rx_ackpkts->dccpap_buf_ackno !=
DCCP_MAX_SEQNO + 1)) DCCP_MAX_SEQNO + 1))
dccp_insert_option_ack_vector(sk, skb); dccp_insert_option_ack_vector(sk, skb);
if (dp->dccps_timestamp_echo != 0) if (dp->dccps_timestamp_echo != 0)
dccp_insert_option_timestamp_echo(sk, skb); dccp_insert_option_timestamp_echo(sk, skb);
} }
ccid_hc_rx_insert_options(dp->dccps_hc_rx_ccid, sk, skb); if (dp->dccps_hc_rx_insert_options) {
ccid_hc_tx_insert_options(dp->dccps_hc_tx_ccid, sk, skb); 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 */ /* 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 * 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 * 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; ap->dccpap_buf_ackno = ackno;
do_gettimeofday(&ap->dccpap_time); dccp_timestamp(sk, &ap->dccpap_time);
out: out:
dccp_pr_debug(""); dccp_pr_debug("");
dccp_ackpkts_print(ap); dccp_ackpkts_print(ap);