aboutsummaryrefslogtreecommitdiff
path: root/net/dccp
diff options
context:
space:
mode:
Diffstat (limited to 'net/dccp')
-rw-r--r--net/dccp/ackvec.c16
-rw-r--r--net/dccp/ackvec.h4
-rw-r--r--net/dccp/ccids/ccid2.c62
-rw-r--r--net/dccp/ccids/ccid2.h2
-rw-r--r--net/dccp/ccids/ccid3.c109
-rw-r--r--net/dccp/ccids/ccid3.h23
-rw-r--r--net/dccp/ccids/lib/loss_interval.c11
-rw-r--r--net/dccp/ccids/lib/loss_interval.h4
-rw-r--r--net/dccp/ccids/lib/packet_history.h9
-rw-r--r--net/dccp/dccp.h65
-rw-r--r--net/dccp/input.c120
-rw-r--r--net/dccp/ipv4.c51
-rw-r--r--net/dccp/ipv6.c46
-rw-r--r--net/dccp/minisocks.c11
-rw-r--r--net/dccp/options.c47
-rw-r--r--net/dccp/output.c151
-rw-r--r--net/dccp/probe.c7
-rw-r--r--net/dccp/proto.c12
-rw-r--r--net/dccp/sysctl.c10
-rw-r--r--net/dccp/timer.c21
20 files changed, 339 insertions, 442 deletions
diff --git a/net/dccp/ackvec.c b/net/dccp/ackvec.c
index 7ac775f9a64..83378f379f7 100644
--- a/net/dccp/ackvec.c
+++ b/net/dccp/ackvec.c
@@ -69,21 +69,20 @@ int dccp_insert_option_ackvec(struct sock *sk, struct sk_buff *skb)
struct dccp_sock *dp = dccp_sk(sk);
struct dccp_ackvec *av = dp->dccps_hc_rx_ackvec;
/* Figure out how many options do we need to represent the ackvec */
- const u16 nr_opts = (av->dccpav_vec_len +
- DCCP_MAX_ACKVEC_OPT_LEN - 1) /
- DCCP_MAX_ACKVEC_OPT_LEN;
+ const u16 nr_opts = DIV_ROUND_UP(av->dccpav_vec_len,
+ DCCP_MAX_ACKVEC_OPT_LEN);
u16 len = av->dccpav_vec_len + 2 * nr_opts, i;
- struct timeval now;
u32 elapsed_time;
const unsigned char *tail, *from;
unsigned char *to;
struct dccp_ackvec_record *avr;
+ suseconds_t delta;
if (DCCP_SKB_CB(skb)->dccpd_opt_len + len > DCCP_MAX_OPT_LEN)
return -1;
- dccp_timestamp(sk, &now);
- elapsed_time = timeval_delta(&now, &av->dccpav_time) / 10;
+ delta = ktime_us_delta(ktime_get_real(), av->dccpav_time);
+ elapsed_time = delta / 10;
if (elapsed_time != 0 &&
dccp_insert_option_elapsed_time(sk, skb, elapsed_time))
@@ -159,8 +158,7 @@ struct dccp_ackvec *dccp_ackvec_alloc(const gfp_t priority)
av->dccpav_buf_head = DCCP_MAX_ACKVEC_LEN - 1;
av->dccpav_buf_ackno = UINT48_MAX + 1;
av->dccpav_buf_nonce = av->dccpav_buf_nonce = 0;
- av->dccpav_time.tv_sec = 0;
- av->dccpav_time.tv_usec = 0;
+ av->dccpav_time = ktime_set(0, 0);
av->dccpav_vec_len = 0;
INIT_LIST_HEAD(&av->dccpav_records);
}
@@ -321,7 +319,7 @@ int dccp_ackvec_add(struct dccp_ackvec *av, const struct sock *sk,
}
av->dccpav_buf_ackno = ackno;
- dccp_timestamp(sk, &av->dccpav_time);
+ av->dccpav_time = ktime_get_real();
out:
return 0;
diff --git a/net/dccp/ackvec.h b/net/dccp/ackvec.h
index 96504a3b16e..9ef0737043e 100644
--- a/net/dccp/ackvec.h
+++ b/net/dccp/ackvec.h
@@ -12,8 +12,8 @@
*/
#include <linux/compiler.h>
+#include <linux/ktime.h>
#include <linux/list.h>
-#include <linux/time.h>
#include <linux/types.h>
/* Read about the ECN nonce to see why it is 253 */
@@ -52,7 +52,7 @@
struct dccp_ackvec {
u64 dccpav_buf_ackno;
struct list_head dccpav_records;
- struct timeval dccpav_time;
+ ktime_t dccpav_time;
u16 dccpav_buf_head;
u16 dccpav_vec_len;
u8 dccpav_buf_nonce;
diff --git a/net/dccp/ccids/ccid2.c b/net/dccp/ccids/ccid2.c
index d29b88fe723..426008e3b7e 100644
--- a/net/dccp/ccids/ccid2.c
+++ b/net/dccp/ccids/ccid2.c
@@ -59,7 +59,8 @@ static void ccid2_hc_tx_check_sanity(const struct ccid2_hc_tx_sock *hctx)
pipe++;
/* packets are sent sequentially */
- BUG_ON(seqp->ccid2s_seq <= prev->ccid2s_seq);
+ BUG_ON(dccp_delta_seqno(seqp->ccid2s_seq,
+ prev->ccid2s_seq ) >= 0);
BUG_ON(time_before(seqp->ccid2s_sent,
prev->ccid2s_sent));
@@ -83,8 +84,7 @@ static void ccid2_hc_tx_check_sanity(const struct ccid2_hc_tx_sock *hctx)
#define ccid2_hc_tx_check_sanity(hctx)
#endif
-static int ccid2_hc_tx_alloc_seq(struct ccid2_hc_tx_sock *hctx, int num,
- gfp_t gfp)
+static int ccid2_hc_tx_alloc_seq(struct ccid2_hc_tx_sock *hctx)
{
struct ccid2_seq *seqp;
int i;
@@ -95,16 +95,16 @@ static int ccid2_hc_tx_alloc_seq(struct ccid2_hc_tx_sock *hctx, int num,
return -ENOMEM;
/* allocate buffer and initialize linked list */
- seqp = kmalloc(sizeof(*seqp) * num, gfp);
+ seqp = kmalloc(CCID2_SEQBUF_LEN * sizeof(struct ccid2_seq), gfp_any());
if (seqp == NULL)
return -ENOMEM;
- for (i = 0; i < (num - 1); i++) {
+ for (i = 0; i < (CCID2_SEQBUF_LEN - 1); i++) {
seqp[i].ccid2s_next = &seqp[i + 1];
seqp[i + 1].ccid2s_prev = &seqp[i];
}
- seqp[num - 1].ccid2s_next = seqp;
- seqp->ccid2s_prev = &seqp[num - 1];
+ seqp[CCID2_SEQBUF_LEN - 1].ccid2s_next = seqp;
+ seqp->ccid2s_prev = &seqp[CCID2_SEQBUF_LEN - 1];
/* This is the first allocation. Initiate the head and tail. */
if (hctx->ccid2hctx_seqbufc == 0)
@@ -114,8 +114,8 @@ static int ccid2_hc_tx_alloc_seq(struct ccid2_hc_tx_sock *hctx, int num,
hctx->ccid2hctx_seqh->ccid2s_next = seqp;
seqp->ccid2s_prev = hctx->ccid2hctx_seqh;
- hctx->ccid2hctx_seqt->ccid2s_prev = &seqp[num - 1];
- seqp[num - 1].ccid2s_next = hctx->ccid2hctx_seqt;
+ hctx->ccid2hctx_seqt->ccid2s_prev = &seqp[CCID2_SEQBUF_LEN - 1];
+ seqp[CCID2_SEQBUF_LEN - 1].ccid2s_next = hctx->ccid2hctx_seqt;
}
/* store the original pointer to the buffer so we can free it */
@@ -127,19 +127,7 @@ static int ccid2_hc_tx_alloc_seq(struct ccid2_hc_tx_sock *hctx, int num,
static int ccid2_hc_tx_send_packet(struct sock *sk, struct sk_buff *skb)
{
- struct ccid2_hc_tx_sock *hctx;
-
- switch (DCCP_SKB_CB(skb)->dccpd_type) {
- case 0: /* XXX data packets from userland come through like this */
- case DCCP_PKT_DATA:
- case DCCP_PKT_DATAACK:
- break;
- /* No congestion control on other packets */
- default:
- return 0;
- }
-
- hctx = ccid2_hc_tx_sk(sk);
+ struct ccid2_hc_tx_sock *hctx = ccid2_hc_tx_sk(sk);
ccid2_pr_debug("pipe=%d cwnd=%d\n", hctx->ccid2hctx_pipe,
hctx->ccid2hctx_cwnd);
@@ -180,16 +168,11 @@ static void ccid2_change_l_ack_ratio(struct sock *sk, int val)
dp->dccps_l_ack_ratio = val;
}
-static void ccid2_change_cwnd(struct ccid2_hc_tx_sock *hctx, int val)
+static void ccid2_change_cwnd(struct ccid2_hc_tx_sock *hctx, u32 val)
{
- if (val == 0)
- val = 1;
-
/* XXX do we need to change ack ratio? */
- ccid2_pr_debug("change cwnd to %d\n", val);
-
- BUG_ON(val < 1);
- hctx->ccid2hctx_cwnd = val;
+ hctx->ccid2hctx_cwnd = val? : 1;
+ ccid2_pr_debug("changed cwnd to %u\n", hctx->ccid2hctx_cwnd);
}
static void ccid2_change_srtt(struct ccid2_hc_tx_sock *hctx, long val)
@@ -295,12 +278,11 @@ static void ccid2_hc_tx_packet_sent(struct sock *sk, int more, unsigned int len)
next = hctx->ccid2hctx_seqh->ccid2s_next;
/* check if we need to alloc more space */
if (next == hctx->ccid2hctx_seqt) {
- int rc;
-
- ccid2_pr_debug("allocating more space in history\n");
- rc = ccid2_hc_tx_alloc_seq(hctx, CCID2_SEQBUF_LEN, gfp_any());
- BUG_ON(rc); /* XXX what do we do? */
-
+ if (ccid2_hc_tx_alloc_seq(hctx)) {
+ DCCP_CRIT("packet history - out of memory!");
+ /* FIXME: find a more graceful way to bail out */
+ return;
+ }
next = hctx->ccid2hctx_seqh->ccid2s_next;
BUG_ON(next == hctx->ccid2hctx_seqt);
}
@@ -581,8 +563,8 @@ static void ccid2_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
hctx->ccid2hctx_rpseq = seqno;
} else {
/* check if packet is consecutive */
- if ((hctx->ccid2hctx_rpseq + 1) == seqno)
- hctx->ccid2hctx_rpseq++;
+ if (dccp_delta_seqno(hctx->ccid2hctx_rpseq, seqno) == 1)
+ hctx->ccid2hctx_rpseq = seqno;
/* it's a later packet */
else if (after48(seqno, hctx->ccid2hctx_rpseq)) {
hctx->ccid2hctx_rpdupack++;
@@ -771,7 +753,7 @@ static int ccid2_hc_tx_init(struct ccid *ccid, struct sock *sk)
hctx->ccid2hctx_seqbufc = 0;
/* XXX init ~ to window size... */
- if (ccid2_hc_tx_alloc_seq(hctx, CCID2_SEQBUF_LEN, GFP_ATOMIC) != 0)
+ if (ccid2_hc_tx_alloc_seq(hctx))
return -ENOMEM;
hctx->ccid2hctx_sent = 0;
@@ -835,7 +817,7 @@ static struct ccid_operations ccid2 = {
};
#ifdef CONFIG_IP_DCCP_CCID2_DEBUG
-module_param(ccid2_debug, int, 0444);
+module_param(ccid2_debug, bool, 0444);
MODULE_PARM_DESC(ccid2_debug, "Enable debug messages");
#endif
diff --git a/net/dccp/ccids/ccid2.h b/net/dccp/ccids/ccid2.h
index ebd79499c85..d9daa534c9b 100644
--- a/net/dccp/ccids/ccid2.h
+++ b/net/dccp/ccids/ccid2.h
@@ -50,7 +50,7 @@ struct ccid2_seq {
* @ccid2hctx_rpdupack - dupacks since rpseq
*/
struct ccid2_hc_tx_sock {
- int ccid2hctx_cwnd;
+ u32 ccid2hctx_cwnd;
int ccid2hctx_ssacks;
int ccid2hctx_acks;
unsigned int ccid2hctx_ssthresh;
diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c
index e91c2b9dc27..25772c32617 100644
--- a/net/dccp/ccids/ccid3.c
+++ b/net/dccp/ccids/ccid3.c
@@ -113,27 +113,24 @@ static inline void ccid3_update_send_interval(struct ccid3_hc_tx_sock *hctx)
hctx->ccid3hctx_s, (unsigned)(hctx->ccid3hctx_x >> 6));
}
-/*
- * Update X by
- * If (p > 0)
- * X_calc = calcX(s, R, p);
- * X = max(min(X_calc, 2 * X_recv), s / t_mbi);
- * Else
- * If (now - tld >= R)
- * X = max(min(2 * X, 2 * X_recv), s / R);
- * tld = now;
+
+/**
+ * ccid3_hc_tx_update_x - Update allowed sending rate X
+ * @stamp: most recent time if available - can be left NULL.
+ * This function tracks draft rfc3448bis, check there for latest details.
*
* Note: X and X_recv are both stored in units of 64 * bytes/second, to support
* fine-grained resolution of sending rates. This requires scaling by 2^6
* throughout the code. Only X_calc is unscaled (in bytes/second).
*
*/
-static void ccid3_hc_tx_update_x(struct sock *sk, struct timeval *now)
+static void ccid3_hc_tx_update_x(struct sock *sk, ktime_t *stamp)
{
struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);
__u64 min_rate = 2 * hctx->ccid3hctx_x_recv;
const __u64 old_x = hctx->ccid3hctx_x;
+ ktime_t now = stamp? *stamp : ktime_get_real();
/*
* Handle IDLE periods: do not reduce below RFC3390 initial sending rate
@@ -153,14 +150,14 @@ static void ccid3_hc_tx_update_x(struct sock *sk, struct timeval *now)
(((__u64)hctx->ccid3hctx_s) << 6) /
TFRC_T_MBI);
- } else if (timeval_delta(now, &hctx->ccid3hctx_t_ld) -
- (suseconds_t)hctx->ccid3hctx_rtt >= 0) {
+ } else if (ktime_us_delta(now, hctx->ccid3hctx_t_ld)
+ - (s64)hctx->ccid3hctx_rtt >= 0) {
hctx->ccid3hctx_x =
max(min(2 * hctx->ccid3hctx_x, min_rate),
scaled_div(((__u64)hctx->ccid3hctx_s) << 6,
hctx->ccid3hctx_rtt));
- hctx->ccid3hctx_t_ld = *now;
+ hctx->ccid3hctx_t_ld = now;
}
if (hctx->ccid3hctx_x != old_x) {
@@ -214,7 +211,6 @@ static void ccid3_hc_tx_no_feedback_timer(unsigned long data)
{
struct sock *sk = (struct sock *)data;
struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);
- struct timeval now;
unsigned long t_nfb = USEC_PER_SEC / 5;
bh_lock_sock(sk);
@@ -265,15 +261,12 @@ static void ccid3_hc_tx_no_feedback_timer(unsigned long data)
max(hctx->ccid3hctx_x_recv / 2,
(((__u64)hctx->ccid3hctx_s) << 6) /
(2 * TFRC_T_MBI));
-
- if (hctx->ccid3hctx_p == 0)
- dccp_timestamp(sk, &now);
} else {
hctx->ccid3hctx_x_recv = hctx->ccid3hctx_x_calc;
hctx->ccid3hctx_x_recv <<= 4;
}
/* Now recalculate X [RFC 3448, 4.3, step (4)] */
- ccid3_hc_tx_update_x(sk, &now);
+ ccid3_hc_tx_update_x(sk, NULL);
/*
* Schedule no feedback timer to expire in
* max(t_RTO, 2 * s/X) = max(t_RTO, 2 * t_ipi)
@@ -309,8 +302,6 @@ static int ccid3_hc_tx_send_packet(struct sock *sk, struct sk_buff *skb)
ktime_t now = ktime_get_real();
s64 delay;
- BUG_ON(hctx == NULL);
-
/*
* This function is called only for Data and DataAck packets. Sending
* zero-sized Data(Ack)s is theoretically possible, but for congestion
@@ -341,7 +332,7 @@ static int ccid3_hc_tx_send_packet(struct sock *sk, struct sk_buff *skb)
ccid3_pr_debug("SYN RTT = %uus\n", dp->dccps_syn_rtt);
hctx->ccid3hctx_rtt = dp->dccps_syn_rtt;
hctx->ccid3hctx_x = rfc3390_initial_rate(sk);
- hctx->ccid3hctx_t_ld = ktime_to_timeval(now);
+ hctx->ccid3hctx_t_ld = now;
} else {
/* Sender does not have RTT sample: X = MSS/second */
hctx->ccid3hctx_x = dp->dccps_mss_cache;
@@ -388,11 +379,8 @@ static void ccid3_hc_tx_packet_sent(struct sock *sk, int more,
unsigned int len)
{
struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);
- struct timeval now;
struct dccp_tx_hist_entry *packet;
- BUG_ON(hctx == NULL);
-
ccid3_hc_tx_update_s(hctx, len);
packet = dccp_tx_hist_entry_new(ccid3_tx_hist, GFP_ATOMIC);
@@ -402,8 +390,7 @@ static void ccid3_hc_tx_packet_sent(struct sock *sk, int more,
}
dccp_tx_hist_add_entry(&hctx->ccid3hctx_hist, packet);
- dccp_timestamp(sk, &now);
- packet->dccphtx_tstamp = now;
+ packet->dccphtx_tstamp = ktime_get_real();
packet->dccphtx_seqno = dccp_sk(sk)->dccps_gss;
packet->dccphtx_rtt = hctx->ccid3hctx_rtt;
packet->dccphtx_sent = 1;
@@ -414,12 +401,10 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
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;
+ ktime_t now;
unsigned long t_nfb;
u32 pinv, r_sample;
- BUG_ON(hctx == NULL);
-
/* we are only interested in ACKs */
if (!(DCCP_SKB_CB(skb)->dccpd_type == DCCP_PKT_ACK ||
DCCP_SKB_CB(skb)->dccpd_type == DCCP_PKT_DATAACK))
@@ -452,13 +437,12 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
else /* can not exceed 100% */
hctx->ccid3hctx_p = 1000000 / pinv;
- dccp_timestamp(sk, &now);
-
+ now = ktime_get_real();
/*
* Calculate new round trip sample as per [RFC 3448, 4.3] by
* R_sample = (now - t_recvdata) - t_elapsed
*/
- r_sample = dccp_sample_rtt(sk, &now, &packet->dccphtx_tstamp);
+ r_sample = dccp_sample_rtt(sk, ktime_us_delta(now, packet->dccphtx_tstamp));
/*
* Update RTT estimate by
@@ -561,8 +545,6 @@ static int ccid3_hc_tx_parse_options(struct sock *sk, unsigned char option,
struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);
struct ccid3_options_received *opt_recv;
- BUG_ON(hctx == NULL);
-
opt_recv = &hctx->ccid3hctx_options_received;
if (opt_recv->ccid3or_seqno != dp->dccps_gsr) {
@@ -636,8 +618,6 @@ static void ccid3_hc_tx_exit(struct sock *sk)
{
struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);
- BUG_ON(hctx == NULL);
-
ccid3_hc_tx_set_state(sk, TFRC_SSTATE_TERM);
sk_stop_timer(sk, &hctx->ccid3hctx_no_feedback_timer);
@@ -647,14 +627,13 @@ static void ccid3_hc_tx_exit(struct sock *sk)
static void ccid3_hc_tx_get_info(struct sock *sk, struct tcp_info *info)
{
- const struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);
+ struct ccid3_hc_tx_sock *hctx;
/* Listen socks doesn't have a private CCID block */
if (sk->sk_state == DCCP_LISTEN)
return;
- BUG_ON(hctx == NULL);
-
+ hctx = ccid3_hc_tx_sk(sk);
info->tcpi_rto = hctx->ccid3hctx_t_rto;
info->tcpi_rtt = hctx->ccid3hctx_rtt;
}
@@ -662,13 +641,14 @@ static void ccid3_hc_tx_get_info(struct sock *sk, struct tcp_info *info)
static int ccid3_hc_tx_getsockopt(struct sock *sk, const int optname, int len,
u32 __user *optval, int __user *optlen)
{
- const struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);
+ const struct ccid3_hc_tx_sock *hctx;
const void *val;
/* Listen socks doesn't have a private CCID block */
if (sk->sk_state == DCCP_LISTEN)
return -EINVAL;
+ hctx = ccid3_hc_tx_sk(sk);
switch (optname) {
case DCCP_SOCKOPT_CCID_TX_INFO:
if (len < sizeof(hctx->ccid3hctx_tfrc))
@@ -729,20 +709,20 @@ 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_rx_hist_entry *packet;
- struct timeval now;
+ ktime_t now;
suseconds_t delta;
ccid3_pr_debug("%s(%p) - entry \n", dccp_role(sk), sk);
- dccp_timestamp(sk, &now);
+ now = ktime_get_real();
switch (hcrx->ccid3hcrx_state) {
case TFRC_RSTATE_NO_DATA:
hcrx->ccid3hcrx_x_recv = 0;
break;
case TFRC_RSTATE_DATA:
- delta = timeval_delta(&now,
- &hcrx->ccid3hcrx_tstamp_last_feedback);
+ delta = ktime_us_delta(now,
+ hcrx->ccid3hcrx_tstamp_last_feedback);
DCCP_BUG_ON(delta < 0);
hcrx->ccid3hcrx_x_recv =
scaled_div32(hcrx->ccid3hcrx_bytes_recv, delta);
@@ -764,7 +744,7 @@ static void ccid3_hc_rx_send_feedback(struct sock *sk)
hcrx->ccid3hcrx_bytes_recv = 0;
/* Elapsed time information [RFC 4340, 13.2] in units of 10 * usecs */
- delta = timeval_delta(&now, &packet->dccphrx_tstamp);
+ delta = ktime_us_delta(now, packet->dccphrx_tstamp);
DCCP_BUG_ON(delta < 0);
hcrx->ccid3hcrx_elapsed_time = delta / 10;
@@ -782,14 +762,13 @@ static void ccid3_hc_rx_send_feedback(struct sock *sk)
static int ccid3_hc_rx_insert_options(struct sock *sk, struct sk_buff *skb)
{
- const struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);
+ const struct ccid3_hc_rx_sock *hcrx;
__be32 x_recv, pinv;
- BUG_ON(hcrx == NULL);
-
if (!(sk->sk_state == DCCP_OPEN || sk->sk_state == DCCP_PARTOPEN))
return 0;
+ hcrx = ccid3_hc_rx_sk(sk);
DCCP_SKB_CB(skb)->dccpd_ccval = hcrx->ccid3hcrx_ccval_last_counter;
if (dccp_packet_without_ack(skb))
@@ -839,7 +818,7 @@ static int ccid3_hc_rx_detect_loss(struct sock *sk,
dccp_li_update_li(sk,
&hcrx->ccid3hcrx_li_hist,
&hcrx->ccid3hcrx_hist,
- &hcrx->ccid3hcrx_tstamp_last_feedback,
+ hcrx->ccid3hcrx_tstamp_last_feedback,
hcrx->ccid3hcrx_s,
hcrx->ccid3hcrx_bytes_recv,
hcrx->ccid3hcrx_x_recv,
@@ -876,11 +855,9 @@ static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb)
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;
u32 p_prev, r_sample, rtt_prev;
int loss, payload_size;
-
- BUG_ON(hcrx == NULL);
+ ktime_t now;
opt_recv = &dccp_sk(sk)->dccps_options_received;
@@ -891,9 +868,9 @@ static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb)
case DCCP_PKT_DATAACK:
if (opt_recv->dccpor_timestamp_echo == 0)
break;
+ r_sample = dccp_timestamp() - opt_recv->dccpor_timestamp_echo;
rtt_prev = hcrx->ccid3hcrx_rtt;
- dccp_timestamp(sk, &now);
- r_sample = dccp_sample_rtt(sk, &now, NULL);
+ r_sample = dccp_sample_rtt(sk, 10 * r_sample);
if (hcrx->ccid3hcrx_state == TFRC_RSTATE_NO_DATA)
hcrx->ccid3hcrx_rtt = r_sample;
@@ -912,7 +889,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, sk, opt_recv->dccpor_ndp,
+ packet = dccp_rx_hist_entry_new(ccid3_rx_hist, opt_recv->dccpor_ndp,
skb, GFP_ATOMIC);
if (unlikely(packet == NULL)) {
DCCP_WARN("%s(%p), Not enough mem to add rx packet "
@@ -941,9 +918,9 @@ static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb)
if (loss)
break;
- dccp_timestamp(sk, &now);
- if ((timeval_delta(&now, &hcrx->ccid3hcrx_tstamp_last_ack) -
- (suseconds_t)hcrx->ccid3hcrx_rtt) >= 0) {
+ now = ktime_get_real();
+ if ((ktime_us_delta(now, hcrx->ccid3hcrx_tstamp_last_ack) -
+ (s64)hcrx->ccid3hcrx_rtt) >= 0) {
hcrx->ccid3hcrx_tstamp_last_ack = now;
ccid3_hc_rx_send_feedback(sk);
}
@@ -984,8 +961,8 @@ static int ccid3_hc_rx_init(struct ccid *ccid, struct sock *sk)
hcrx->ccid3hcrx_state = TFRC_RSTATE_NO_DATA;
INIT_LIST_HEAD(&hcrx->ccid3hcrx_hist);
INIT_LIST_HEAD(&hcrx->ccid3hcrx_li_hist);
- dccp_timestamp(sk, &hcrx->ccid3hcrx_tstamp_last_ack);
- hcrx->ccid3hcrx_tstamp_last_feedback = hcrx->ccid3hcrx_tstamp_last_ack;
+ hcrx->ccid3hcrx_tstamp_last_feedback =
+ hcrx->ccid3hcrx_tstamp_last_ack = ktime_get_real();
hcrx->ccid3hcrx_s = 0;
hcrx->ccid3hcrx_rtt = 0;
return 0;
@@ -995,8 +972,6 @@ static void ccid3_hc_rx_exit(struct sock *sk)
{
struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);
- BUG_ON(hcrx == NULL);
-
ccid3_hc_rx_set_state(sk, TFRC_RSTATE_TERM);
/* Empty packet history */
@@ -1008,14 +983,13 @@ 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 ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);
+ const struct ccid3_hc_rx_sock *hcrx;
/* Listen socks doesn't have a private CCID block */
if (sk->sk_state == DCCP_LISTEN)
return;
- BUG_ON(hcrx == NULL);
-
+ hcrx = ccid3_hc_rx_sk(sk);
info->tcpi_ca_state = hcrx->ccid3hcrx_state;
info->tcpi_options |= TCPI_OPT_TIMESTAMPS;
info->tcpi_rcv_rtt = hcrx->ccid3hcrx_rtt;
@@ -1024,13 +998,14 @@ static void ccid3_hc_rx_get_info(struct sock *sk, struct tcp_info *info)
static int ccid3_hc_rx_getsockopt(struct sock *sk, const int optname, int len,
u32 __user *optval, int __user *optlen)
{
- const struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);
+ const struct ccid3_hc_rx_sock *hcrx;
const void *val;
/* Listen socks doesn't have a private CCID block */
if (sk->sk_state == DCCP_LISTEN)
return -EINVAL;
+ hcrx = ccid3_hc_rx_sk(sk);
switch (optname) {
case DCCP_SOCKOPT_CCID_RX_INFO:
if (len < sizeof(hcrx->ccid3hcrx_tfrc))
@@ -1071,7 +1046,7 @@ static struct ccid_operations ccid3 = {
};
#ifdef CONFIG_IP_DCCP_CCID3_DEBUG
-module_param(ccid3_debug, int, 0444);
+module_param(ccid3_debug, bool, 0444);
MODULE_PARM_DESC(ccid3_debug, "Enable debug messages");
#endif
diff --git a/net/dccp/ccids/ccid3.h b/net/dccp/ccids/ccid3.h
index 51d4b804e33..0cdc982cfe4 100644
--- a/net/dccp/ccids/ccid3.h
+++ b/net/dccp/ccids/ccid3.h
@@ -38,7 +38,6 @@
#include <linux/ktime.h>
#include <linux/list.h>
-#include <linux/time.h>
#include <linux/types.h>
#include <linux/tfrc.h>
#include "../ccid.h"
@@ -111,13 +110,20 @@ struct ccid3_hc_tx_sock {
u8 ccid3hctx_idle;
ktime_t ccid3hctx_t_last_win_count;
struct timer_list ccid3hctx_no_feedback_timer;
- struct timeval ccid3hctx_t_ld;
+ ktime_t ccid3hctx_t_ld;
ktime_t ccid3hctx_t_nom;
u32 ccid3hctx_delta;
struct list_head ccid3hctx_hist;
struct ccid3_options_received ccid3hctx_options_received;
};
+static inline struct ccid3_hc_tx_sock *ccid3_hc_tx_sk(const struct sock *sk)
+{
+ struct ccid3_hc_tx_sock *hctx = ccid_priv(dccp_sk(sk)->dccps_hc_tx_ccid);
+ BUG_ON(hctx == NULL);
+ return hctx;
+}
+
/* TFRC receiver states */
enum ccid3_hc_rx_states {
TFRC_RSTATE_NO_DATA = 1,
@@ -153,8 +159,8 @@ struct ccid3_hc_rx_sock {
ccid3hcrx_ccval_last_counter:4;
enum ccid3_hc_rx_states ccid3hcrx_state:8;
u32 ccid3hcrx_bytes_recv;
- struct timeval ccid3hcrx_tstamp_last_feedback;
- struct timeval ccid3hcrx_tstamp_last_ack;
+ ktime_t ccid3hcrx_tstamp_last_feedback;
+ ktime_t ccid3hcrx_tstamp_last_ack;
struct list_head ccid3hcrx_hist;
struct list_head ccid3hcrx_li_hist;
u16 ccid3hcrx_s;
@@ -162,14 +168,11 @@ struct ccid3_hc_rx_sock {
u32 ccid3hcrx_elapsed_time;
};
-static inline struct ccid3_hc_tx_sock *ccid3_hc_tx_sk(const struct sock *sk)
-{
- return ccid_priv(dccp_sk(sk)->dccps_hc_tx_ccid);
-}
-
static inline struct ccid3_hc_rx_sock *ccid3_hc_rx_sk(const struct sock *sk)
{
- return ccid_priv(dccp_sk(sk)->dccps_hc_rx_ccid);
+ struct ccid3_hc_rx_sock *hcrx = ccid_priv(dccp_sk(sk)->dccps_hc_rx_ccid);
+ BUG_ON(hcrx == NULL);
+ return hcrx;
}
#endif /* _DCCP_CCID3_H_ */
diff --git a/net/dccp/ccids/lib/loss_interval.c b/net/dccp/ccids/lib/loss_interval.c
index 174d3f13d93..40ad428a27f 100644
--- a/net/dccp/ccids/lib/loss_interval.c
+++ b/net/dccp/ccids/lib/loss_interval.c
@@ -125,14 +125,14 @@ static int dccp_li_hist_interval_new(struct list_head *list,
* returns estimated loss interval in usecs */
static u32 dccp_li_calc_first_li(struct sock *sk,
struct list_head *hist_list,
- struct timeval *last_feedback,
+ ktime_t last_feedback,
u16 s, u32 bytes_recv,
u32 previous_x_recv)
{
struct dccp_rx_hist_entry *entry, *next, *tail = NULL;
u32 x_recv, p;
suseconds_t rtt, delta;
- struct timeval tstamp = { 0, 0 };
+ ktime_t tstamp = ktime_set(0, 0);
int interval = 0;
int win_count = 0;
int step = 0;
@@ -176,7 +176,7 @@ found:
return ~0;
}
- delta = timeval_delta(&tstamp, &tail->dccphrx_tstamp);
+ delta = ktime_us_delta(tstamp, tail->dccphrx_tstamp);
DCCP_BUG_ON(delta < 0);
rtt = delta * 4 / interval;
@@ -196,8 +196,7 @@ found:
return ~0;
}
- dccp_timestamp(sk, &tstamp);
- delta = timeval_delta(&tstamp, last_feedback);
+ delta = ktime_us_delta(ktime_get_real(), last_feedback);
DCCP_BUG_ON(delta <= 0);
x_recv = scaled_div32(bytes_recv, delta);
@@ -226,7 +225,7 @@ found:
void dccp_li_update_li(struct sock *sk,
struct list_head *li_hist_list,
struct list_head *hist_list,
- struct timeval *last_feedback, u16 s, u32 bytes_recv,
+ ktime_t last_feedback, u16 s, u32 bytes_recv,
u32 previous_x_recv, u64 seq_loss, u8 win_loss)
{
struct dccp_li_hist_entry *head;
diff --git a/net/dccp/ccids/lib/loss_interval.h b/net/dccp/ccids/lib/loss_interval.h
index 906c806d6d9..27bee92dae1 100644
--- a/net/dccp/ccids/lib/loss_interval.h
+++ b/net/dccp/ccids/lib/loss_interval.h
@@ -13,8 +13,8 @@
* any later version.
*/
+#include <linux/ktime.h>
#include <linux/list.h>
-#include <linux/time.h>
extern void dccp_li_hist_purge(struct list_head *list);
@@ -23,7 +23,7 @@ extern u32 dccp_li_hist_calc_i_mean(struct list_head *list);
extern void dccp_li_update_li(struct sock *sk,
struct list_head *li_hist_list,
struct list_head *hist_list,
- struct timeval *last_feedback, u16 s,
+ ktime_t last_feedback, u16 s,
u32 bytes_recv, u32 previous_x_recv,
u64 seq_loss, u8 win_loss);
#endif /* _DCCP_LI_HIST_ */
diff --git a/net/dccp/ccids/lib/packet_history.h b/net/dccp/ccids/lib/packet_history.h
index 60d00f01539..032bb61c6e3 100644
--- a/net/dccp/ccids/lib/packet_history.h
+++ b/net/dccp/ccids/lib/packet_history.h
@@ -37,9 +37,9 @@
#ifndef _DCCP_PKT_HIST_
#define _DCCP_PKT_HIST_
+#include <linux/ktime.h>
#include <linux/list.h>
#include <linux/slab.h>
-#include <linux/time.h>
#include "../../dccp.h"
@@ -57,7 +57,7 @@ struct dccp_tx_hist_entry {
u64 dccphtx_seqno:48,
dccphtx_sent:1;
u32 dccphtx_rtt;
- struct timeval dccphtx_tstamp;
+ ktime_t dccphtx_tstamp;
};
struct dccp_tx_hist {
@@ -124,7 +124,7 @@ struct dccp_rx_hist_entry {
dccphrx_ccval:4,
dccphrx_type:4;
u32 dccphrx_ndp; /* In fact it is from 8 to 24 bits */
- struct timeval dccphrx_tstamp;
+ ktime_t dccphrx_tstamp;
};
struct dccp_rx_hist {
@@ -136,7 +136,6 @@ extern void dccp_rx_hist_delete(struct dccp_rx_hist *hist);
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 gfp_t prio)
@@ -151,7 +150,7 @@ static inline struct dccp_rx_hist_entry *
entry->dccphrx_ccval = dh->dccph_ccval;
entry->dccphrx_type = dh->dccph_type;
entry->dccphrx_ndp = ndp;
- dccp_timestamp(sk, &entry->dccphrx_tstamp);
+ entry->dccphrx_tstamp = ktime_get_real();
}
return entry;
diff --git a/net/dccp/dccp.h b/net/dccp/dccp.h
index e2d74cd7eee..ee97950d77d 100644
--- a/net/dccp/dccp.h
+++ b/net/dccp/dccp.h
@@ -13,6 +13,7 @@
*/
#include <linux/dccp.h>
+#include <linux/ktime.h>
#include <net/snmp.h>
#include <net/sock.h>
#include <net/tcp.h>
@@ -91,6 +92,7 @@ extern int sysctl_dccp_feat_ack_ratio;
extern int sysctl_dccp_feat_send_ack_vector;
extern int sysctl_dccp_feat_send_ndp_count;
extern int sysctl_dccp_tx_qlen;
+extern int sysctl_dccp_sync_ratelimit;
/*
* 48-bit sequence number arithmetic (signed and unsigned)
@@ -208,7 +210,6 @@ extern void dccp_v4_send_check(struct sock *sk, int len, struct sk_buff *skb);
extern int dccp_retransmit_skb(struct sock *sk, struct sk_buff *skb);
extern void dccp_send_ack(struct sock *sk);
-extern void dccp_send_delayed_ack(struct sock *sk);
extern void dccp_reqsk_send_ack(struct sk_buff *sk, struct request_sock *rsk);
extern void dccp_send_sync(struct sock *sk, const u64 seq,
@@ -293,11 +294,12 @@ extern unsigned int dccp_poll(struct file *file, struct socket *sock,
extern int dccp_v4_connect(struct sock *sk, struct sockaddr *uaddr,
int addr_len);
+extern struct sk_buff *dccp_ctl_make_reset(struct socket *ctl,
+ struct sk_buff *skb);
extern int dccp_send_reset(struct sock *sk, enum dccp_reset_codes code);
extern void dccp_send_close(struct sock *sk, const int active);
extern int dccp_invalid_packet(struct sk_buff *skb);
-extern u32 dccp_sample_rtt(struct sock *sk, struct timeval *t_recv,
- struct timeval *t_history);
+extern u32 dccp_sample_rtt(struct sock *sk, long delta);
static inline int dccp_bad_service_code(const struct sock *sk,
const __be32 service)
@@ -309,10 +311,22 @@ static inline int dccp_bad_service_code(const struct sock *sk,
return !dccp_list_has_service(dp->dccps_service_list, service);
}
+/**
+ * dccp_skb_cb - DCCP per-packet control information
+ * @dccpd_type: one of %dccp_pkt_type (or unknown)
+ * @dccpd_ccval: CCVal field (5.1), see e.g. RFC 4342, 8.1
+ * @dccpd_reset_code: one of %dccp_reset_codes
+ * @dccpd_reset_data: Data1..3 fields (depend on @dccpd_reset_code)
+ * @dccpd_opt_len: total length of all options (5.8) in the packet
+ * @dccpd_seq: sequence number
+ * @dccpd_ack_seq: acknowledgment number subheader field value
+ * This is used for transmission as well as for reception.
+ */
struct dccp_skb_cb {
__u8 dccpd_type:4;
__u8 dccpd_ccval:4;
- __u8 dccpd_reset_code;
+ __u8 dccpd_reset_code,
+ dccpd_reset_data[3];
__u16 dccpd_opt_len;
__u64 dccpd_seq;
__u64 dccpd_ack_seq;
@@ -395,53 +409,14 @@ extern int dccp_insert_options(struct sock *sk, struct sk_buff *skb);
extern int dccp_insert_option_elapsed_time(struct sock *sk,
struct sk_buff *skb,
u32 elapsed_time);
+extern u32 dccp_timestamp(void);
+extern void dccp_timestamping_init(void);
extern int dccp_insert_option_timestamp(struct sock *sk,
struct sk_buff *skb);
extern int dccp_insert_option(struct sock *sk, struct sk_buff *skb,
unsigned char option,
const void *value, unsigned char len);
-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;
-}
-
-static inline suseconds_t timeval_delta(const struct timeval *large,
- const struct timeval *small)
-{
- time_t secs = large->tv_sec - small->tv_sec;
- suseconds_t usecs = large->tv_usec - small->tv_usec;
-
- if (usecs < 0) {
- secs--;
- usecs += USEC_PER_SEC;
- }
- return secs * USEC_PER_SEC + usecs;
-}
-
-static inline void timeval_add_usecs(struct timeval *tv,
- const suseconds_t usecs)
-{
- tv->tv_usec += usecs;