Commit 7fedd7e5 authored by David S. Miller's avatar David S. Miller
parents 1a19eb75 37efb03f
...@@ -91,19 +91,16 @@ static inline u64 rfc3390_initial_rate(struct sock *sk) ...@@ -91,19 +91,16 @@ static inline u64 rfc3390_initial_rate(struct sock *sk)
return scaled_div(w_init << 6, hc->tx_rtt); 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) 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); 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) */ ccid3_pr_debug("t_ipi=%u, s=%u, X=%u\n", hc->tx_t_ipi,
hc->tx_delta = min_t(u32, hc->tx_t_ipi / 2, TFRC_OPSYS_HALF_TIME_GRAN); hc->tx_s, (unsigned)(hc->tx_x >> 6));
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));
} }
static u32 ccid3_hc_tx_idle_rtt(struct ccid3_hc_tx_sock *hc, ktime_t now) 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) ...@@ -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); delay = ktime_us_delta(hc->tx_t_nom, now);
ccid3_pr_debug("delay=%ld\n", (long)delay); 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) * if (t_now > t_nom - delta)
* // send the packet now * // send the packet now
* else * else
* // send the packet in (t_nom - t_now) milliseconds. * // send the packet in (t_nom - t_now) milliseconds.
*/ */
if (delay - (s64)hc->tx_delta >= 1000) if (delay >= TFRC_T_DELTA)
return (u32)delay / 1000L; return (u32)delay / USEC_PER_MSEC;
ccid3_hc_tx_update_win_count(hc, now); ccid3_hc_tx_update_win_count(hc, now);
break; break;
...@@ -373,6 +370,7 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) ...@@ -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_hc_tx_sock *hc = ccid3_hc_tx_sk(sk);
struct ccid3_options_received *opt_recv = &hc->tx_options_received; struct ccid3_options_received *opt_recv = &hc->tx_options_received;
struct tfrc_tx_hist_entry *acked;
ktime_t now; ktime_t now;
unsigned long t_nfb; unsigned long t_nfb;
u32 pinv, r_sample; u32 pinv, r_sample;
...@@ -386,17 +384,24 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) ...@@ -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) hc->tx_state != TFRC_SSTATE_NO_FBACK)
return; return;
now = ktime_get_real(); /*
* Locate the acknowledged packet in the TX history.
/* Estimate RTT from history if ACK number is valid */ *
r_sample = tfrc_tx_hist_rtt(hc->tx_hist, * Returning "entry not found" here can for instance happen when
DCCP_SKB_CB(skb)->dccpd_ack_seq, now); * - the host has not sent out anything (e.g. a passive server),
if (r_sample == 0) { * - the Ack is outdated (packet with higher Ack number was received),
DCCP_WARN("%s(%p): %s with bogus ACK-%llu\n", dccp_role(sk), sk, * - it is a bogus Ack (for a packet not sent on this connection).
dccp_packet_name(DCCP_SKB_CB(skb)->dccpd_type), */
(unsigned long long)DCCP_SKB_CB(skb)->dccpd_ack_seq); acked = tfrc_tx_hist_find_entry(hc->tx_hist, dccp_hdr_ack_seq(skb));
if (acked == NULL)
return; 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 */ /* Update receive rate in units of 64 * bytes/second */
hc->tx_x_recv = opt_recv->ccid3or_receive_rate; 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) ...@@ -408,11 +413,7 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
hc->tx_p = 0; hc->tx_p = 0;
else /* can not exceed 100% */ else /* can not exceed 100% */
hc->tx_p = scaled_div(1, pinv); 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 * 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, ...@@ -484,60 +485,31 @@ static int ccid3_hc_tx_parse_options(struct sock *sk, unsigned char option,
unsigned char len, u16 idx, unsigned char len, u16 idx,
unsigned char *value) 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_hc_tx_sock *hc = ccid3_hc_tx_sk(sk);
struct ccid3_options_received *opt_recv = &hc->tx_options_received; struct ccid3_options_received *opt_recv = &hc->tx_options_received;
__be32 opt_val; __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) { switch (option) {
case TFRC_OPT_RECEIVE_RATE:
case TFRC_OPT_LOSS_EVENT_RATE: case TFRC_OPT_LOSS_EVENT_RATE:
if (unlikely(len != 4)) { if (unlikely(len != 4)) {
DCCP_WARN("%s(%p), invalid len %d " DCCP_WARN("%s(%p), invalid len %d for %u\n",
"for TFRC_OPT_LOSS_EVENT_RATE\n", dccp_role(sk), sk, len, option);
dccp_role(sk), sk, len); return -EINVAL;
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);
} }
break; opt_val = ntohl(get_unaligned((__be32 *)value));
case TFRC_OPT_LOSS_INTERVALS:
opt_recv->ccid3or_loss_intervals_idx = idx; if (option == TFRC_OPT_RECEIVE_RATE) {
opt_recv->ccid3or_loss_intervals_len = len; opt_recv->ccid3or_receive_rate = opt_val;
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);
ccid3_pr_debug("%s(%p), RECEIVE_RATE=%u\n", ccid3_pr_debug("%s(%p), RECEIVE_RATE=%u\n",
dccp_role(sk), sk, dccp_role(sk), sk, opt_val);
opt_recv->ccid3or_receive_rate); } 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 0;
return rc;
} }
static int ccid3_hc_tx_init(struct ccid *ccid, struct sock *sk) static int ccid3_hc_tx_init(struct ccid *ccid, struct sock *sk)
......
...@@ -45,12 +45,22 @@ ...@@ -45,12 +45,22 @@
/* Two seconds as per RFC 5348, 4.2 */ /* Two seconds as per RFC 5348, 4.2 */
#define TFRC_INITIAL_TIMEOUT (2 * USEC_PER_SEC) #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 */ /* Parameter t_mbi from [RFC 3448, 4.3]: backoff interval in seconds */
#define TFRC_T_MBI 64 #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 { enum ccid3_options {
TFRC_OPT_LOSS_EVENT_RATE = 192, TFRC_OPT_LOSS_EVENT_RATE = 192,
TFRC_OPT_LOSS_INTERVALS = 193, TFRC_OPT_LOSS_INTERVALS = 193,
...@@ -58,9 +68,6 @@ enum ccid3_options { ...@@ -58,9 +68,6 @@ enum ccid3_options {
}; };
struct ccid3_options_received { 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_loss_event_rate;
u32 ccid3or_receive_rate; u32 ccid3or_receive_rate;
}; };
...@@ -90,7 +97,6 @@ enum ccid3_hc_tx_states { ...@@ -90,7 +97,6 @@ enum ccid3_hc_tx_states {
* @tx_no_feedback_timer: Handle to no feedback timer * @tx_no_feedback_timer: Handle to no feedback timer
* @tx_t_ld: Time last doubled during slow start * @tx_t_ld: Time last doubled during slow start
* @tx_t_nom: Nominal send time of next packet * @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_hist: Packet history
* @tx_options_received: Parsed set of retrieved options * @tx_options_received: Parsed set of retrieved options
*/ */
...@@ -109,7 +115,6 @@ struct ccid3_hc_tx_sock { ...@@ -109,7 +115,6 @@ struct ccid3_hc_tx_sock {
struct timer_list tx_no_feedback_timer; struct timer_list tx_no_feedback_timer;
ktime_t tx_t_ld; ktime_t tx_t_ld;
ktime_t tx_t_nom; ktime_t tx_t_nom;
u32 tx_delta;
struct tfrc_tx_hist_entry *tx_hist; struct tfrc_tx_hist_entry *tx_hist;
struct ccid3_options_received tx_options_received; struct ccid3_options_received tx_options_received;
}; };
......
...@@ -38,18 +38,6 @@ ...@@ -38,18 +38,6 @@
#include "packet_history.h" #include "packet_history.h"
#include "../../dccp.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 * Transmitter History Routines
*/ */
...@@ -71,15 +59,6 @@ void tfrc_tx_packet_history_exit(void) ...@@ -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) 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()); 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) ...@@ -107,24 +86,6 @@ void tfrc_tx_hist_purge(struct tfrc_tx_hist_entry **headp)
*headp = NULL; *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 * Receiver History Routines
*/ */
......
...@@ -40,12 +40,28 @@ ...@@ -40,12 +40,28 @@
#include <linux/slab.h> #include <linux/slab.h>
#include "tfrc.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 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 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 */ /* Subtraction a-b modulo-16, respects circular wrap-around */
#define SUB16(a, b) (((a) + 16 - (b)) & 0xF) #define SUB16(a, b) (((a) + 16 - (b)) & 0xF)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment