* net/dccp/ccids/ccid3.c
*
* Copyright (c) 2005 The University of Waikato, Hamilton, New Zealand.
+ * Copyright (c) 2005 Ian McDonald <iam4@cs.waikato.ac.nz>
*
* An implementation of the DCCP protocol
*
* This code has been developed by the University of Waikato WAND
* research group. For further information please see http://www.wand.net.nz/
- * or e-mail Ian McDonald - iam4@cs.waikato.ac.nz
*
* This code also uses code from Lulea University, rereleased as GPL by its
* authors:
static struct dccp_tx_hist *ccid3_tx_hist;
static struct dccp_rx_hist *ccid3_rx_hist;
-static kmem_cache_t *ccid3_loss_interval_hist_slab;
+static kmem_cache_t *ccid3_loss_interval_hist_slab __read_mostly;
static inline struct ccid3_loss_interval_hist_entry *
ccid3_loss_interval_hist_entry_new(const unsigned int __nocast prio)
}
}
-/* returns the difference in usecs between timeval passed in and current time */
-static inline u32 now_delta(struct timeval tv) {
- struct timeval now;
-
- do_gettimeofday(&now);
- return ((now.tv_sec-tv.tv_sec)*1000000+now.tv_usec-tv.tv_usec);
-}
-
#define CALCX_ARRSIZE 500
#define CALCX_SPLIT 50000
hctx->ccid3hctx_x = 10;
}
/* Schedule no feedback timer to expire in max(4 * R, 2 * s / X) */
- next_tmout = max_t(u32, inet_csk(sk)->icsk_rto,
+ next_tmout = max_t(u32, hctx->ccid3hctx_t_rto,
2 * (hctx->ccid3hctx_s * 100000) / (hctx->ccid3hctx_x / 10));
break;
default:
struct ccid3_hc_tx_sock *hctx = dp->dccps_hc_tx_ccid_private;
struct timeval now;
-// ccid3_pr_debug("%s, sk=%p, more=%d, len=%d\n", dccp_role(sk), sk, more, len);
BUG_ON(hctx == NULL);
if (hctx->ccid3hctx_state == TFRC_SSTATE_TERM) {
struct ccid3_options_received *opt_recv;
struct dccp_tx_hist_entry *packet;
unsigned long next_tmout;
- u16 t_elapsed;
+ u32 t_elapsed;
u32 pinv;
u32 x_recv;
u32 r_sample;
r_sample);
/* Update timeout interval */
- inet_csk(sk)->icsk_rto = max_t(u32, 4 * hctx->ccid3hctx_rtt,
- USEC_PER_SEC);
+ hctx->ccid3hctx_t_rto = max_t(u32, 4 * hctx->ccid3hctx_rtt,
+ USEC_PER_SEC);
/* Update receive rate */
hctx->ccid3hctx_x_recv = x_recv; /* x_recv in bytes per second */
/* to prevent divide by zero below */
/* Schedule no feedback timer to expire in max(4 * R, 2 * s / X) */
- next_tmout = max(inet_csk(sk)->icsk_rto,
+ next_tmout = max(hctx->ccid3hctx_t_rto,
(2 * (hctx->ccid3hctx_s * 100000) /
(hctx->ccid3hctx_x / 10)));
/* maths with 100000 and 10 is to prevent overflow with 32 bit */
hctx->ccid3hctx_x = hctx->ccid3hctx_s; /* set transmission rate to 1 packet per second */
hctx->ccid3hctx_rtt = 4; /* See ccid3_hc_tx_packet_sent win_count calculatation */
- inet_csk(sk)->icsk_rto = USEC_PER_SEC;
+ hctx->ccid3hctx_t_rto = USEC_PER_SEC;
hctx->ccid3hctx_state = TFRC_SSTATE_NO_SENT;
INIT_LIST_HEAD(&hctx->ccid3hctx_hist);
init_timer(&hctx->ccid3hctx_no_feedback_timer);
static void ccid3_hc_rx_insert_options(struct sock *sk, struct sk_buff *skb)
{
const struct dccp_sock *dp = dccp_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))
return;
- if (hcrx->ccid3hcrx_elapsed_time != 0 && !dccp_packet_without_ack(skb))
- dccp_insert_option_elapsed_time(sk, skb, hcrx->ccid3hcrx_elapsed_time);
-
- if (DCCP_SKB_CB(skb)->dccpd_type != DCCP_PKT_DATA) {
- const u32 x_recv = htonl(hcrx->ccid3hcrx_x_recv);
- const u32 pinv = htonl(hcrx->ccid3hcrx_pinv);
-
- dccp_insert_option(sk, skb, TFRC_OPT_LOSS_EVENT_RATE, &pinv, sizeof(pinv));
- dccp_insert_option(sk, skb, TFRC_OPT_RECEIVE_RATE, &x_recv, sizeof(x_recv));
- }
-
DCCP_SKB_CB(skb)->dccpd_ccval = hcrx->ccid3hcrx_last_counter;
+
+ if (dccp_packet_without_ack(skb))
+ return;
+
+ if (hcrx->ccid3hcrx_elapsed_time != 0)
+ dccp_insert_option_elapsed_time(sk, skb,
+ hcrx->ccid3hcrx_elapsed_time);
+ dccp_insert_option_timestamp(sk, skb);
+ x_recv = htonl(hcrx->ccid3hcrx_x_recv);
+ pinv = htonl(hcrx->ccid3hcrx_pinv);
+ dccp_insert_option(sk, skb, TFRC_OPT_LOSS_EVENT_RATE,
+ &pinv, sizeof(pinv));
+ dccp_insert_option(sk, skb, TFRC_OPT_RECEIVE_RATE,
+ &x_recv, sizeof(x_recv));
}
/* Weights used to calculate loss event rate */
struct ccid3_hc_rx_sock *hcrx = dp->dccps_hc_rx_ccid_private;
struct dccp_rx_hist_entry *entry, *next, *tail = NULL;
u32 rtt, delta, x_recv, fval, p, tmp2;
- struct timeval tstamp, tmp_tv;
+ struct timeval tstamp = { 0 }, tmp_tv;
int interval = 0;
int win_count = 0;
int step = 0;
{
struct dccp_sock *dp = dccp_sk(sk);
struct ccid3_hc_rx_sock *hcrx = dp->dccps_hc_rx_ccid_private;
+ const struct dccp_options_received *opt_recv;
struct dccp_rx_hist_entry *packet;
struct timeval now;
+ u32 now_usecs;
u8 win_count;
u32 p_prev;
int ins;
BUG_ON(!(hcrx->ccid3hcrx_state == TFRC_RSTATE_NO_DATA ||
hcrx->ccid3hcrx_state == TFRC_RSTATE_DATA));
+ opt_recv = &dp->dccps_options_received;
+
switch (DCCP_SKB_CB(skb)->dccpd_type) {
case DCCP_PKT_ACK:
if (hcrx->ccid3hcrx_state == TFRC_RSTATE_NO_DATA)
return;
case DCCP_PKT_DATAACK:
- if (dp->dccps_options_received.dccpor_timestamp_echo == 0)
+ if (opt_recv->dccpor_timestamp_echo == 0)
break;
p_prev = hcrx->ccid3hcrx_rtt;
do_gettimeofday(&now);
- /* hcrx->ccid3hcrx_rtt = now - dp->dccps_options_received.dccpor_timestamp_echo -
- usecs_to_jiffies(dp->dccps_options_received.dccpor_elapsed_time * 10);
- FIXME - I think above code is broken - have to look at options more, will also need
- to fix pr_debug below */
+ now_usecs = now.tv_sec * USEC_PER_SEC + now.tv_usec;
+ hcrx->ccid3hcrx_rtt = now_usecs -
+ (opt_recv->dccpor_timestamp_echo -
+ opt_recv->dccpor_elapsed_time) * 10;
if (p_prev != hcrx->ccid3hcrx_rtt)
- ccid3_pr_debug("%s, sk=%p, New RTT estimate=%lu jiffies, tstamp_echo=%u, elapsed time=%u\n",
- dccp_role(sk), sk, hcrx->ccid3hcrx_rtt,
- dp->dccps_options_received.dccpor_timestamp_echo,
- dp->dccps_options_received.dccpor_elapsed_time);
+ ccid3_pr_debug("%s, New RTT=%luus, elapsed time=%u\n",
+ dccp_role(sk), hcrx->ccid3hcrx_rtt,
+ opt_recv->dccpor_elapsed_time);
break;
case DCCP_PKT_DATA:
break;
return;
}
- packet = dccp_rx_hist_entry_new(ccid3_rx_hist,
- dp->dccps_options_received.dccpor_ndp,
+ packet = dccp_rx_hist_entry_new(ccid3_rx_hist, opt_recv->dccpor_ndp,
skb, SLAB_ATOMIC);
if (packet == NULL) {
ccid3_pr_debug("%s, sk=%p, Not enough mem to add rx packet to history (consider it lost)!",
case TFRC_RSTATE_DATA:
hcrx->ccid3hcrx_bytes_recv += skb->len - dccp_hdr(skb)->dccph_doff * 4;
if (ins == 0) {
- do_gettimeofday(&now);
- if ((now_delta(hcrx->ccid3hcrx_tstamp_last_ack)) >= hcrx->ccid3hcrx_rtt) {
- hcrx->ccid3hcrx_tstamp_last_ack = now;
+ if (now_delta(hcrx->ccid3hcrx_tstamp_last_ack) >=
+ hcrx->ccid3hcrx_rtt) {
+ do_gettimeofday(&hcrx->ccid3hcrx_tstamp_last_ack);
ccid3_hc_rx_send_feedback(sk);
}
return;
}
/* Dealing with packet loss */
- ccid3_pr_debug("%s, sk=%p(%s), skb=%p, data loss! Reacting...\n",
- dccp_role(sk), sk, dccp_state_name(sk->sk_state), skb);
+ ccid3_pr_debug("%s, sk=%p(%s), data loss! Reacting...\n",
+ dccp_role(sk), sk, dccp_state_name(sk->sk_state));
ccid3_hc_rx_detect_loss(sk);
p_prev = hcrx->ccid3hcrx_p;
hcrx->ccid3hcrx_state = TFRC_RSTATE_NO_DATA;
INIT_LIST_HEAD(&hcrx->ccid3hcrx_hist);
INIT_LIST_HEAD(&hcrx->ccid3hcrx_loss_interval_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;
return 0;
}
dp->dccps_hc_rx_ccid_private = NULL;
}
+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;
+
+ if (hcrx == NULL)
+ return;
+
+ info->tcpi_ca_state = hcrx->ccid3hcrx_state;
+ info->tcpi_options |= TCPI_OPT_TIMESTAMPS;
+ info->tcpi_rcv_rtt = hcrx->ccid3hcrx_rtt;
+}
+
+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;
+
+ if (hctx == NULL)
+ return;
+
+ info->tcpi_rto = hctx->ccid3hctx_t_rto;
+ info->tcpi_rtt = hctx->ccid3hctx_rtt;
+}
+
static struct ccid ccid3 = {
.ccid_id = 3,
.ccid_name = "ccid3",
.ccid_hc_rx_exit = ccid3_hc_rx_exit,
.ccid_hc_rx_insert_options = ccid3_hc_rx_insert_options,
.ccid_hc_rx_packet_recv = ccid3_hc_rx_packet_recv,
+ .ccid_hc_rx_get_info = ccid3_hc_rx_get_info,
+ .ccid_hc_tx_get_info = ccid3_hc_tx_get_info,
};
module_param(ccid3_debug, int, 0444);