summaryrefslogtreecommitdiffstats
path: root/net/dccp
diff options
context:
space:
mode:
Diffstat (limited to 'net/dccp')
-rw-r--r--net/dccp/ccids/ccid3.c153
-rw-r--r--net/dccp/ccids/ccid3.h9
-rw-r--r--net/dccp/ccids/lib/loss_interval.c36
-rw-r--r--net/dccp/ccids/lib/loss_interval.h9
-rw-r--r--net/dccp/ccids/lib/packet_history.c168
-rw-r--r--net/dccp/ccids/lib/packet_history.h17
-rw-r--r--net/dccp/ccids/lib/tfrc.h2
-rw-r--r--net/dccp/ccids/lib/tfrc_equation.c2
-rw-r--r--net/dccp/dccp.h10
-rw-r--r--net/dccp/feat.h2
-rw-r--r--net/dccp/ipv4.c3
-rw-r--r--net/dccp/ipv6.c8
-rw-r--r--net/dccp/options.c4
-rw-r--r--net/dccp/proto.c4
14 files changed, 210 insertions, 217 deletions
diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c
index c39bff706cf..090bc39e819 100644
--- a/net/dccp/ccids/ccid3.c
+++ b/net/dccp/ccids/ccid3.c
@@ -2,7 +2,7 @@
* net/dccp/ccids/ccid3.c
*
* Copyright (c) 2005 The University of Waikato, Hamilton, New Zealand.
- * Copyright (c) 2005-6 Ian McDonald <imcdnzl@gmail.com>
+ * Copyright (c) 2005-6 Ian McDonald <ian.mcdonald@jandi.co.nz>
*
* An implementation of the DCCP protocol
*
@@ -342,6 +342,8 @@ static int ccid3_hc_tx_send_packet(struct sock *sk,
new_packet->dccphtx_ccval =
DCCP_SKB_CB(skb)->dccpd_ccval =
hctx->ccid3hctx_last_win_count;
+ timeval_add_usecs(&hctx->ccid3hctx_t_nom,
+ hctx->ccid3hctx_t_ipi);
}
out:
return rc;
@@ -413,7 +415,8 @@ static void ccid3_hc_tx_packet_sent(struct sock *sk, int more, int len)
case TFRC_SSTATE_NO_FBACK:
case TFRC_SSTATE_FBACK:
if (len > 0) {
- hctx->ccid3hctx_t_nom = now;
+ timeval_sub_usecs(&hctx->ccid3hctx_t_nom,
+ hctx->ccid3hctx_t_ipi);
ccid3_calc_new_t_ipi(hctx);
ccid3_calc_new_delta(hctx);
timeval_add_usecs(&hctx->ccid3hctx_t_nom,
@@ -757,8 +760,7 @@ static void ccid3_hc_rx_send_feedback(struct sock *sk)
}
hcrx->ccid3hcrx_tstamp_last_feedback = now;
- hcrx->ccid3hcrx_last_counter = packet->dccphrx_ccval;
- hcrx->ccid3hcrx_seqno_last_counter = packet->dccphrx_seqno;
+ hcrx->ccid3hcrx_ccval_last_counter = packet->dccphrx_ccval;
hcrx->ccid3hcrx_bytes_recv = 0;
/* Convert to multiples of 10us */
@@ -782,7 +784,7 @@ static int ccid3_hc_rx_insert_options(struct sock *sk, struct sk_buff *skb)
if (!(sk->sk_state == DCCP_OPEN || sk->sk_state == DCCP_PARTOPEN))
return 0;
- DCCP_SKB_CB(skb)->dccpd_ccval = hcrx->ccid3hcrx_last_counter;
+ DCCP_SKB_CB(skb)->dccpd_ccval = hcrx->ccid3hcrx_ccval_last_counter;
if (dccp_packet_without_ack(skb))
return 0;
@@ -854,6 +856,11 @@ static u32 ccid3_hc_rx_calc_first_li(struct sock *sk)
interval = 1;
}
found:
+ if (!tail) {
+ LIMIT_NETDEBUG(KERN_WARNING "%s: tail is null\n",
+ __FUNCTION__);
+ return ~0;
+ }
rtt = timeval_delta(&tstamp, &tail->dccphrx_tstamp) * 4 / interval;
ccid3_pr_debug("%s, sk=%p, approximated RTT to %uus\n",
dccp_role(sk), sk, rtt);
@@ -864,9 +871,20 @@ found:
delta = timeval_delta(&tstamp, &hcrx->ccid3hcrx_tstamp_last_feedback);
x_recv = usecs_div(hcrx->ccid3hcrx_bytes_recv, delta);
+ if (x_recv == 0)
+ x_recv = hcrx->ccid3hcrx_x_recv;
+
tmp1 = (u64)x_recv * (u64)rtt;
do_div(tmp1,10000000);
tmp2 = (u32)tmp1;
+
+ if (!tmp2) {
+ LIMIT_NETDEBUG(KERN_WARNING "tmp2 = 0 "
+ "%s: x_recv = %u, rtt =%u\n",
+ __FUNCTION__, x_recv, rtt);
+ return ~0;
+ }
+
fval = (hcrx->ccid3hcrx_s * 100000) / tmp2;
/* do not alter order above or you will get overflow on 32 bit */
p = tfrc_calc_x_reverse_lookup(fval);
@@ -882,31 +900,101 @@ found:
static void ccid3_hc_rx_update_li(struct sock *sk, u64 seq_loss, u8 win_loss)
{
struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);
+ struct dccp_li_hist_entry *next, *head;
+ u64 seq_temp;
- if (seq_loss != DCCP_MAX_SEQNO + 1 &&
- list_empty(&hcrx->ccid3hcrx_li_hist)) {
- struct dccp_li_hist_entry *li_tail;
+ if (list_empty(&hcrx->ccid3hcrx_li_hist)) {
+ if (!dccp_li_hist_interval_new(ccid3_li_hist,
+ &hcrx->ccid3hcrx_li_hist, seq_loss, win_loss))
+ return;
- li_tail = dccp_li_hist_interval_new(ccid3_li_hist,
- &hcrx->ccid3hcrx_li_hist,
- seq_loss, win_loss);
- if (li_tail == NULL)
+ next = (struct dccp_li_hist_entry *)
+ hcrx->ccid3hcrx_li_hist.next;
+ next->dccplih_interval = ccid3_hc_rx_calc_first_li(sk);
+ } else {
+ struct dccp_li_hist_entry *entry;
+ struct list_head *tail;
+
+ head = (struct dccp_li_hist_entry *)
+ hcrx->ccid3hcrx_li_hist.next;
+ /* FIXME win count check removed as was wrong */
+ /* should make this check with receive history */
+ /* and compare there as per section 10.2 of RFC4342 */
+
+ /* new loss event detected */
+ /* calculate last interval length */
+ seq_temp = dccp_delta_seqno(head->dccplih_seqno, seq_loss);
+ entry = dccp_li_hist_entry_new(ccid3_li_hist, SLAB_ATOMIC);
+
+ if (entry == NULL) {
+ printk(KERN_CRIT "%s: out of memory\n",__FUNCTION__);
+ dump_stack();
return;
- li_tail->dccplih_interval = ccid3_hc_rx_calc_first_li(sk);
- } else
- LIMIT_NETDEBUG(KERN_WARNING "%s: FIXME: find end of "
- "interval\n", __FUNCTION__);
+ }
+
+ list_add(&entry->dccplih_node, &hcrx->ccid3hcrx_li_hist);
+
+ tail = hcrx->ccid3hcrx_li_hist.prev;
+ list_del(tail);
+ kmem_cache_free(ccid3_li_hist->dccplih_slab, tail);
+
+ /* Create the newest interval */
+ entry->dccplih_seqno = seq_loss;
+ entry->dccplih_interval = seq_temp;
+ entry->dccplih_win_count = win_loss;
+ }
}
-static void ccid3_hc_rx_detect_loss(struct sock *sk)
+static int ccid3_hc_rx_detect_loss(struct sock *sk,
+ struct dccp_rx_hist_entry *packet)
{
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,
- &win_loss);
+ struct dccp_rx_hist_entry *rx_hist = dccp_rx_hist_head(&hcrx->ccid3hcrx_hist);
+ u64 seqno = packet->dccphrx_seqno;
+ u64 tmp_seqno;
+ int loss = 0;
+ u8 ccval;
+
+
+ tmp_seqno = hcrx->ccid3hcrx_seqno_nonloss;
+
+ if (!rx_hist ||
+ follows48(packet->dccphrx_seqno, hcrx->ccid3hcrx_seqno_nonloss)) {
+ hcrx->ccid3hcrx_seqno_nonloss = seqno;
+ hcrx->ccid3hcrx_ccval_nonloss = packet->dccphrx_ccval;
+ goto detect_out;
+ }
+
- ccid3_hc_rx_update_li(sk, seq_loss, win_loss);
+ while (dccp_delta_seqno(hcrx->ccid3hcrx_seqno_nonloss, seqno)
+ > TFRC_RECV_NUM_LATE_LOSS) {
+ loss = 1;
+ ccid3_hc_rx_update_li(sk, hcrx->ccid3hcrx_seqno_nonloss,
+ hcrx->ccid3hcrx_ccval_nonloss);
+ tmp_seqno = hcrx->ccid3hcrx_seqno_nonloss;
+ dccp_inc_seqno(&tmp_seqno);
+ hcrx->ccid3hcrx_seqno_nonloss = tmp_seqno;
+ dccp_inc_seqno(&tmp_seqno);
+ while (dccp_rx_hist_find_entry(&hcrx->ccid3hcrx_hist,
+ tmp_seqno, &ccval)) {
+ hcrx->ccid3hcrx_seqno_nonloss = tmp_seqno;
+ hcrx->ccid3hcrx_ccval_nonloss = ccval;
+ dccp_inc_seqno(&tmp_seqno);
+ }
+ }
+
+ /* FIXME - this code could be simplified with above while */
+ /* but works at moment */
+ if (follows48(packet->dccphrx_seqno, hcrx->ccid3hcrx_seqno_nonloss)) {
+ hcrx->ccid3hcrx_seqno_nonloss = seqno;
+ hcrx->ccid3hcrx_ccval_nonloss = packet->dccphrx_ccval;
+ }
+
+detect_out:
+ dccp_rx_hist_add_packet(ccid3_rx_hist, &hcrx->ccid3hcrx_hist,
+ &hcrx->ccid3hcrx_li_hist, packet,
+ hcrx->ccid3hcrx_seqno_nonloss);
+ return loss;
}
static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb)
@@ -916,8 +1004,8 @@ static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb)
struct dccp_rx_hist_entry *packet;
struct timeval now;
u8 win_count;
- u32 p_prev, r_sample, t_elapsed;
- int ins;
+ u32 p_prev, rtt_prev, r_sample, t_elapsed;
+ int loss;
BUG_ON(hcrx == NULL ||
!(hcrx->ccid3hcrx_state == TFRC_RSTATE_NO_DATA ||
@@ -932,7 +1020,7 @@ 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;
- p_prev = hcrx->ccid3hcrx_rtt;
+ rtt_prev = hcrx->ccid3hcrx_rtt;
dccp_timestamp(sk, &now);
timeval_sub_usecs(&now, opt_recv->dccpor_timestamp_echo * 10);
r_sample = timeval_usecs(&now);
@@ -951,8 +1039,8 @@ static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb)
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",
+ if (rtt_prev != hcrx->ccid3hcrx_rtt)
+ ccid3_pr_debug("%s, New RTT=%uus, elapsed time=%u\n",
dccp_role(sk), hcrx->ccid3hcrx_rtt,
opt_recv->dccpor_elapsed_time);
break;
@@ -973,8 +1061,7 @@ static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb)
win_count = packet->dccphrx_ccval;
- ins = dccp_rx_hist_add_packet(ccid3_rx_hist, &hcrx->ccid3hcrx_hist,
- &hcrx->ccid3hcrx_li_hist, packet);
+ loss = ccid3_hc_rx_detect_loss(sk, packet);
if (DCCP_SKB_CB(skb)->dccpd_type == DCCP_PKT_ACK)
return;
@@ -991,7 +1078,7 @@ static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb)
case TFRC_RSTATE_DATA:
hcrx->ccid3hcrx_bytes_recv += skb->len -
dccp_hdr(skb)->dccph_doff * 4;
- if (ins != 0)
+ if (loss)
break;
dccp_timestamp(sk, &now);
@@ -1012,7 +1099,6 @@ static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *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;
/* Calculate loss event rate */
@@ -1022,6 +1108,9 @@ static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb)
/* Scaling up by 1000000 as fixed decimal */
if (i_mean != 0)
hcrx->ccid3hcrx_p = 1000000 / i_mean;
+ } else {
+ printk(KERN_CRIT "%s: empty loss hist\n",__FUNCTION__);
+ dump_stack();
}
if (hcrx->ccid3hcrx_p > p_prev) {
@@ -1230,7 +1319,7 @@ static __exit void ccid3_module_exit(void)
}
module_exit(ccid3_module_exit);
-MODULE_AUTHOR("Ian McDonald <iam4@cs.waikato.ac.nz>, "
+MODULE_AUTHOR("Ian McDonald <ian.mcdonald@jandi.co.nz>, "
"Arnaldo Carvalho de Melo <acme@ghostprotocols.net>");
MODULE_DESCRIPTION("DCCP TFRC CCID3 CCID");
MODULE_LICENSE("GPL");
diff --git a/net/dccp/ccids/ccid3.h b/net/dccp/ccids/ccid3.h
index 5ade4f668b2..0a2cb7536d2 100644
--- a/net/dccp/ccids/ccid3.h
+++ b/net/dccp/ccids/ccid3.h
@@ -1,13 +1,13 @@
/*
* net/dccp/ccids/ccid3.h
*
- * Copyright (c) 2005 The University of Waikato, Hamilton, New Zealand.
+ * Copyright (c) 2005-6 The University of Waikato, Hamilton, New Zealand.
*
* 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
+ * or e-mail Ian McDonald - ian.mcdonald@jandi.co.nz
*
* This code also uses code from Lulea University, rereleased as GPL by its
* authors:
@@ -120,9 +120,10 @@ struct ccid3_hc_rx_sock {
#define ccid3hcrx_x_recv ccid3hcrx_tfrc.tfrcrx_x_recv
#define ccid3hcrx_rtt ccid3hcrx_tfrc.tfrcrx_rtt
#define ccid3hcrx_p ccid3hcrx_tfrc.tfrcrx_p
- u64 ccid3hcrx_seqno_last_counter:48,
+ u64 ccid3hcrx_seqno_nonloss:48,
+ ccid3hcrx_ccval_nonloss:4,
ccid3hcrx_state:8,
- ccid3hcrx_last_counter:4;
+ ccid3hcrx_ccval_last_counter:4;
u32 ccid3hcrx_bytes_recv;
struct timeval ccid3hcrx_tstamp_last_feedback;
struct timeval ccid3hcrx_tstamp_last_ack;
diff --git a/net/dccp/ccids/lib/loss_interval.c b/net/dccp/ccids/lib/loss_interval.c
index 5d7b7d86438..906c81ab9d4 100644
--- a/net/dccp/ccids/lib/loss_interval.c
+++ b/net/dccp/ccids/lib/loss_interval.c
@@ -2,7 +2,7 @@
* net/dccp/ccids/lib/loss_interval.c
*
* Copyright (c) 2005 The University of Waikato, Hamilton, New Zealand.
- * Copyright (c) 2005 Ian McDonald <iam4@cs.waikato.ac.nz>
+ * Copyright (c) 2005-6 Ian McDonald <ian.mcdonald@jandi.co.nz>
* Copyright (c) 2005 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
*
* This program is free software; you can redistribute it and/or modify
@@ -12,6 +12,7 @@
*/
#include <linux/module.h>
+#include <net/sock.h>
#include "loss_interval.h"
@@ -90,13 +91,13 @@ u32 dccp_li_hist_calc_i_mean(struct list_head *list)
u32 w_tot = 0;
list_for_each_entry_safe(li_entry, li_next, list, dccplih_node) {
- if (i < DCCP_LI_HIST_IVAL_F_LENGTH) {
+ if (li_entry->dccplih_interval != ~0) {
i_tot0 += li_entry->dccplih_interval * dccp_li_hist_w[i];
w_tot += dccp_li_hist_w[i];
+ if (i != 0)
+ i_tot1 += li_entry->dccplih_interval * dccp_li_hist_w[i - 1];
}
- if (i != 0)
- i_tot1 += li_entry->dccplih_interval * dccp_li_hist_w[i - 1];
if (++i > DCCP_LI_HIST_IVAL_F_LENGTH)
break;
@@ -107,37 +108,36 @@ u32 dccp_li_hist_calc_i_mean(struct list_head *list)
i_tot = max(i_tot0, i_tot1);
- /* FIXME: Why do we do this? -Ian McDonald */
- if (i_tot * 4 < w_tot)
- i_tot = w_tot * 4;
+ if (!w_tot) {
+ LIMIT_NETDEBUG(KERN_WARNING "%s: w_tot = 0\n", __FUNCTION__);
+ return 1;
+ }
- return i_tot * 4 / w_tot;
+ return i_tot / w_tot;
}
EXPORT_SYMBOL_GPL(dccp_li_hist_calc_i_mean);
-struct dccp_li_hist_entry *dccp_li_hist_interval_new(struct dccp_li_hist *hist,
- struct list_head *list,
- const u64 seq_loss,
- const u8 win_loss)
+int dccp_li_hist_interval_new(struct dccp_li_hist *hist,
+ struct list_head *list, const u64 seq_loss, const u8 win_loss)
{
- struct dccp_li_hist_entry *tail = NULL, *entry;
+ struct dccp_li_hist_entry *entry;
int i;
- for (i = 0; i <= DCCP_LI_HIST_IVAL_F_LENGTH; ++i) {
+ for (i = 0; i < DCCP_LI_HIST_IVAL_F_LENGTH; i++) {
entry = dccp_li_hist_entry_new(hist, SLAB_ATOMIC);
if (entry == NULL) {
dccp_li_hist_purge(hist, list);
- return NULL;
+ dump_stack();
+ return 0;
}
- if (tail == NULL)
- tail = entry;
+ entry->dccplih_interval = ~0;
list_add(&entry->dccplih_node, list);
}
entry->dccplih_seqno = seq_loss;
entry->dccplih_win_count = win_loss;
- return tail;
+ return 1;
}
EXPORT_SYMBOL_GPL(dccp_li_hist_interval_new);
diff --git a/net/dccp/ccids/lib/loss_interval.h b/net/dccp/ccids/lib/loss_interval.h
index 43bf78269d1..0ae85f0340b 100644
--- a/net/dccp/ccids/lib/loss_interval.h
+++ b/net/dccp/ccids/lib/loss_interval.h
@@ -4,7 +4,7 @@
* net/dccp/ccids/lib/loss_interval.h
*
* Copyright (c) 2005 The University of Waikato, Hamilton, New Zealand.
- * Copyright (c) 2005 Ian McDonald <iam4@cs.waikato.ac.nz>
+ * Copyright (c) 2005 Ian McDonald <ian.mcdonald@jandi.co.nz>
* Copyright (c) 2005 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
*
* This program is free software; you can redistribute it and/or modify it
@@ -52,9 +52,6 @@ extern void dccp_li_hist_purge(struct dccp_li_hist *hist,
extern u32 dccp_li_hist_calc_i_mean(struct list_head *list);
-extern struct dccp_li_hist_entry *
- dccp_li_hist_interval_new(struct dccp_li_hist *hist,
- struct list_head *list,
- const u64 seq_loss,
- const u8 win_loss);
+extern int dccp_li_hist_interval_new(struct dccp_li_hist *hist,
+ struct list_head *list, const u64 seq_loss, const u8 win_loss);
#endif /* _DCCP_LI_HIST_ */
diff --git a/net/dccp/ccids/lib/packet_history.c b/net/dccp/ccids/lib/packet_history.c
index ad98d6a322e..b876c9c81c6 100644
--- a/net/dccp/ccids/lib/packet_history.c
+++ b/net/dccp/ccids/lib/packet_history.c
@@ -1,13 +1,13 @@
/*
- * net/dccp/packet_history.h
+ * net/dccp/packet_history.c
*
- * Copyright (c) 2005 The University of Waikato, Hamilton, New Zealand.
+ * Copyright (c) 2005-6 The University of Waikato, Hamilton, New Zealand.
*
* 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
+ * or e-mail Ian McDonald - ian.mcdonald@jandi.co.nz
*
* This code also uses code from Lulea University, rereleased as GPL by its
* authors:
@@ -112,64 +112,27 @@ struct dccp_rx_hist_entry *
EXPORT_SYMBOL_GPL(dccp_rx_hist_find_data_packet);
-int dccp_rx_hist_add_packet(struct dccp_rx_hist *hist,
+void dccp_rx_hist_add_packet(struct dccp_rx_hist *hist,
struct list_head *rx_list,
struct list_head *li_list,
- struct dccp_rx_hist_entry *packet)
+ struct dccp_rx_hist_entry *packet,
+ u64 nonloss_seqno)
{
- struct dccp_rx_hist_entry *entry, *next, *iter;
+ struct dccp_rx_hist_entry *entry, *next;
u8 num_later = 0;
- iter = dccp_rx_hist_head(rx_list);
- if (iter == NULL)
- dccp_rx_hist_add_entry(rx_list, packet);
- else {
- const u64 seqno = packet->dccphrx_seqno;
-
- if (after48(seqno, iter->dccphrx_seqno))
- dccp_rx_hist_add_entry(rx_list, packet);
- else {
- if (dccp_rx_hist_entry_data_packet(iter))
- num_later = 1;
-
- list_for_each_entry_continue(iter, rx_list,
- dccphrx_node) {
- if (after48(seqno, iter->dccphrx_seqno)) {
- dccp_rx_hist_add_entry(&iter->dccphrx_node,
- packet);
- goto trim_history;
- }
-
- if (dccp_rx_hist_entry_data_packet(iter))
- num_later++;
+ list_add(&packet->dccphrx_node, rx_list);
- if (num_later == TFRC_RECV_NUM_LATE_LOSS) {
- dccp_rx_hist_entry_delete(hist, packet);
- return 1;
- }
- }
-
- if (num_later < TFRC_RECV_NUM_LATE_LOSS)
- dccp_rx_hist_add_entry(rx_list, packet);
- /*
- * FIXME: else what? should we destroy the packet
- * like above?
- */
- }
- }
-
-trim_history:
- /*
- * Trim history (remove all packets after the NUM_LATE_LOSS + 1
- * data packets)
- */
num_later = TFRC_RECV_NUM_LATE_LOSS + 1;
if (!list_empty(li_list)) {
list_for_each_entry_safe(entry, next, rx_list, dccphrx_node) {
if (num_later == 0) {
- list_del_init(&entry->dccphrx_node);
- dccp_rx_hist_entry_delete(hist, entry);
+ if (after48(nonloss_seqno,
+ entry->dccphrx_seqno)) {
+ list_del_init(&entry->dccphrx_node);
+ dccp_rx_hist_entry_delete(hist, entry);
+ }
} else if (dccp_rx_hist_entry_data_packet(entry))
--num_later;
}
@@ -217,94 +180,10 @@ trim_history:
--num_later;
}
}
-
- return 0;
}
EXPORT_SYMBOL_GPL(dccp_rx_hist_add_packet);
-u64 dccp_rx_hist_detect_loss(struct list_head *rx_list,
- struct list_head *li_list, u8 *win_loss)
-{
- struct dccp_rx_hist_entry *entry, *next, *packet;
- struct dccp_rx_hist_entry *a_loss = NULL;
- struct dccp_rx_hist_entry *b_loss = NULL;
- u64 seq_loss = DCCP_MAX_SEQNO + 1;
- u8 num_later = TFRC_RECV_NUM_LATE_LOSS;
-
- list_for_each_entry_safe(entry, next, rx_list, dccphrx_node) {
- if (num_later == 0) {
- b_loss = entry;
- break;
- } else if (dccp_rx_hist_entry_data_packet(entry))
- --num_later;
- }
-
- if (b_loss == NULL)
- goto out;
-
- num_later = 1;
- list_for_each_entry_safe_continue(entry, next, rx_list, dccphrx_node) {
- if (num_later == 0) {
- a_loss = entry;
- break;
- } else if (dccp_rx_hist_entry_data_packet(entry))
- --num_later;
- }
-
- if (a_loss == NULL) {
- if (list_empty(li_list)) {
- /* no loss event have occured yet */
- LIMIT_NETDEBUG("%s: TODO: find a lost data packet by "
- "comparing to initial seqno\n",
- __FUNCTION__);
- goto out;
- } else {
- LIMIT_NETDEBUG("%s: Less than 4 data pkts in history!",
- __FUNCTION__);
- goto out;
- }
- }
-
- /* Locate a lost data packet */
- entry = packet = b_loss;
- list_for_each_entry_safe_continue(entry, next, rx_list, dccphrx_node) {
- u64 delta = dccp_delta_seqno(entry->dccphrx_seqno,
- packet->dccphrx_seqno);
-
- if (delta != 0) {
- if (dccp_rx_hist_entry_data_packet(packet))
- --delta;
- /*
- * FIXME: check this, probably this % usage is because
- * in earlier drafts the ndp count was just 8 bits
- * long, but now it cam be up to 24 bits long.
- */
-#if 0
- if (delta % DCCP_NDP_LIMIT !=
- (packet->dccphrx_ndp -
- entry->dccphrx_ndp) % DCCP_NDP_LIMIT)
-#endif
- if (delta != packet->dccphrx_ndp - entry->dccphrx_ndp) {
- seq_loss = entry->dccphrx_seqno;
- dccp_inc_seqno(&seq_loss);
- }
- }
- packet = entry;
- if (packet == a_loss)
- break;
- }
-out:
- if (seq_loss != DCCP_MAX_SEQNO + 1)
- *win_loss = a_loss->dccphrx_ccval;
- else
- *win_loss = 0; /* Paranoia */
-
- return seq_loss;
-}
-
-EXPORT_SYMBOL_GPL(dccp_rx_hist_detect_loss);
-
struct dccp_tx_hist *dccp_tx_hist_new(const char *name)
{
struct dccp_tx_hist *hist = kmalloc(sizeof(*hist), GFP_ATOMIC);
@@ -365,6 +244,25 @@ struct dccp_tx_hist_entry *
EXPORT_SYMBOL_GPL(dccp_tx_hist_find_entry);
+int dccp_rx_hist_find_entry(const struct list_head *list, const u64 seq,
+ u8 *ccval)
+{
+ struct dccp_rx_hist_entry *packet = NULL, *entry;
+
+ list_for_each_entry(entry, list, dccphrx_node)
+ if (entry->dccphrx_seqno == seq) {
+ packet = entry;
+ break;
+ }
+
+ if (packet)
+ *ccval = packet->dccphrx_ccval;
+
+ return packet != NULL;
+}
+
+EXPORT_SYMBOL_GPL(dccp_rx_hist_find_entry);
+
void dccp_tx_hist_purge_older(struct dccp_tx_hist *hist,
struct list_head *list,
struct dccp_tx_hist_entry *packet)
@@ -391,7 +289,7 @@ void dccp_tx_hist_purge(struct dccp_tx_hist *hist, struct list_head *list)
EXPORT_SYMBOL_GPL(dccp_tx_hist_purge);
-MODULE_AUTHOR("Ian McDonald <iam4@cs.waikato.ac.nz>, "
+MODULE_AUTHOR("Ian McDonald <ian.mcdonald@jandi.co.nz>, "
"Arnaldo Carvalho de Melo <acme@ghostprotocols.net>");
MODULE_DESCRIPTION("DCCP TFRC library");
MODULE_LICENSE("GPL");
diff --git a/net/dccp/ccids/lib/packet_history.h b/net/dccp/ccids/lib/packet_history.h
index 673c209e4e8..067cf1c85a3 100644
--- a/net/dccp/ccids/lib/packet_history.h
+++ b/net/dccp/ccids/lib/packet_history.h
@@ -1,13 +1,13 @@
/*
* net/dccp/packet_history.h
*
- * Copyright (c) 2005 The University of Waikato, Hamilton, New Zealand.
+ * Copyright (c) 2005-6 The University of Waikato, Hamilton, New Zealand.
*
* 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
+ * or e-mail Ian McDonald - ian.mcdonald@jandi.co.nz
*
* This code also uses code from Lulea University, rereleased as GPL by its
* authors:
@@ -106,6 +106,8 @@ static inline void dccp_tx_hist_entry_delete(struct dccp_tx_hist *hist,
extern struct dccp_tx_hist_entry *
dccp_tx_hist_find_entry(const struct list_head *list,
const u64 seq);
+extern int dccp_rx_hist_find_entry(const struct list_head *list, const u64 seq,
+ u8 *ccval);
static inline void dccp_tx_hist_add_entry(struct list_head *list,
struct dccp_tx_hist_entry *entry)
@@ -164,12 +166,6 @@ static inline void dccp_rx_hist_entry_delete(struct dccp_rx_hist *hist,
extern void dccp_rx_hist_purge(struct dccp_rx_hist *hist,
struct list_head *list);
-static inline void dccp_rx_hist_add_entry(struct list_head *list,
- struct dccp_rx_hist_entry *entry)
-{
- list_add(&entry->dccphrx_node, list);
-}
-
static inline struct dccp_rx_hist_entry *
dccp_rx_hist_head(struct list_head *list)
{
@@ -188,10 +184,11 @@ static inline int
entry->dccphrx_type == DCCP_PKT_DATAACK;
}
-extern int dccp_rx_hist_add_packet(struct dccp_rx_hist *hist,
+extern void dccp_rx_hist_add_packet(struct dccp_rx_hist *hist,
struct list_head *rx_list,
struct list_head *li_list,
- struct dccp_rx_hist_entry *packet);
+ struct dccp_rx_hist_entry *packet,
+ u64 nonloss_seqno);
extern u64 dccp_rx_hist_detect_loss(struct list_head *rx_list,
struct list_head *li_list, u8 *win_loss);
diff --git a/net/dccp/ccids/lib/tfrc.h b/net/dccp/ccids/lib/tfrc.h
index 130c4c40cfe..45f30f59ea2 100644
--- a/net/dccp/ccids/lib/tfrc.h
+++ b/net/dccp/ccids/lib/tfrc.h
@@ -4,7 +4,7 @@
* net/dccp/ccids/lib/tfrc.h
*
* Copyright (c) 2005 The University of Waikato, Hamilton, New Zealand.
- * Copyright (c) 2005 Ian McDonald <iam4@cs.waikato.ac.nz>
+ * Copyright (c) 2005 Ian McDonald <ian.mcdonald@jandi.co.nz>
* Copyright (c) 2005 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
* Copyright (c) 2003 Nils-Erik Mattsson, Joacim Haggmark, Magnus Erixzon
*
diff --git a/net/dccp/ccids/lib/tfrc_equation.c b/net/dccp/ccids/lib/tfrc_equation.c
index 4fd2ebebf5a..44076e0c659 100644
--- a/net/dccp/ccids/lib/tfrc_equation.c
+++ b/net/dccp/ccids/lib/tfrc_equation.c
@@ -2,7 +2,7 @@
* net/dccp/ccids/lib/tfrc_equation.c
*
* Copyright (c) 2005 The University of Waikato, Hamilton, New Zealand.
- * Copyright (c) 2005 Ian McDonald <iam4@cs.waikato.ac.nz>
+ * Copyright (c) 2005 Ian McDonald <ian.mcdonald@jandi.co.nz>
* Copyright (c) 2005 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
* Copyright (c) 2003 Nils-Erik Mattsson, Joacim Haggmark, Magnus Erixzon
*
diff --git a/net/dccp/dccp.h b/net/dccp/dccp.h
index d00a2f4ee5d..a5c5475724c 100644
--- a/net/dccp/dccp.h
+++ b/net/dccp/dccp.h
@@ -5,7 +5,7 @@
*
* An implementation of the DCCP protocol
* Copyright (c) 2005 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
- * Copyright (c) 2005 Ian McDonald <iam4@cs.waikato.ac.nz>
+ * Copyright (c) 2005-6 Ian McDonald <ian.mcdonald@jandi.co.nz>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as
@@ -81,6 +81,14 @@ static inline u64 max48(const u64 seq1, const u64 seq2)
return after48(seq1, seq2) ? seq1 : seq2;
}
+/* is seq1 next seqno after seq2 */
+static inline int follows48(const u64 seq1, const u64 seq2)
+{
+ int diff = (seq1 & 0xFFFF) - (seq2 & 0xFFFF);
+
+ return diff==1;
+}
+
enum {
DCCP_MIB_NUM = 0,
DCCP_MIB_ACTIVEOPENS, /* ActiveOpens */
diff --git a/net/dccp/feat.h b/net/dccp/feat.h
index 6048373c718..b44c45504fb 100644
--- a/net/dccp/feat.h
+++ b/net/dccp/feat.h
@@ -26,4 +26,6 @@ extern void dccp_feat_clean(struct dccp_minisock *dmsk);
extern int dccp_feat_clone(struct sock *oldsk, struct sock *newsk);
extern int dccp_feat_init(struct dccp_minisock *dmsk);
+extern int dccp_feat_default_sequence_window;
+
#endif /* _DCCP_FEAT_H */
diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c
index c3073e7e81d..7f56f7e8f57 100644
--- a/net/dccp/ipv4.c
+++ b/net/dccp/ipv4.c
@@ -504,8 +504,7 @@ int dccp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
ireq = inet_rsk(req);
ireq->loc_addr = daddr;
ireq->rmt_addr = saddr;
- req->rcv_wnd = 100; /* Fake, option parsing will get the
- right value */
+ req->rcv_wnd = dccp_feat_default_sequence_window;
ireq->opt = NULL;
/*
diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c
index ff42bc43263..610c722ac27 100644
--- a/net/dccp/ipv6.c
+++ b/net/dccp/ipv6.c
@@ -31,6 +31,7 @@
#include "dccp.h"
#include "ipv6.h"
+#include "feat.h"
/* Socket used for sending RSTs and ACKs */
static struct socket *dccp_v6_ctl_socket;
@@ -229,7 +230,7 @@ static int dccp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
ipv6_addr_copy(&np->saddr, saddr);
inet->rcv_saddr = LOOPBACK4_IPV6;
- ip6_dst_store(sk, dst, NULL);
+ __ip6_dst_store(sk, dst, NULL);
icsk->icsk_ext_hdr_len = 0;
if (np->opt != NULL)
@@ -707,8 +708,7 @@ static int dccp_v6_conn_request(struct sock *sk, struct sk_buff *skb)
ireq = inet_rsk(req);
ipv6_addr_copy(&ireq6->rmt_addr, &skb->nh.ipv6h->saddr);
ipv6_addr_copy(&ireq6->loc_addr, &skb->nh.ipv6h->daddr);
- req->rcv_wnd = 100; /* Fake, option parsing will get the
- right value */
+ req->rcv_wnd = dccp_feat_default_sequence_window;
ireq6->pktopts = NULL;
if (ipv6_opt_accepted(sk, skb) ||
@@ -863,7 +863,7 @@ static struct sock *dccp_v6_request_recv_sock(struct sock *sk,
* comment in that function for the gory details. -acme
*/
- ip6_dst_store(newsk, dst, NULL);
+ __ip6_dst_store(newsk, dst, NULL);
newsk->sk_route_caps = dst->dev->features & ~(NETIF_F_IP_CSUM |
NETIF_F_TSO);
newdp6 = (struct dccp6_sock *)newsk;
diff --git a/net/dccp/options.c b/net/dccp/options.c
index c3cda1e39aa..07a34696ac9 100644
--- a/net/dccp/options.c
+++ b/net/dccp/options.c
@@ -4,7 +4,7 @@
* An implementation of the DCCP protocol
* Copyright (c) 2005 Aristeu Sergio Rozanski Filho <aris@cathedrallabs.org>
* Copyright (c) 2005 Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
- * Copyright (c) 2005 Ian McDonald <iam4@cs.waikato.ac.nz>
+ * Copyright (c) 2005 Ian McDonald <ian.mcdonald@jandi.co.nz>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -29,6 +29,8 @@ int dccp_feat_default_ack_ratio = DCCPF_INITIAL_ACK_RATIO;
int dccp_feat_default_send_ack_vector = DCCPF_INITIAL_SEND_ACK_VECTOR;
int dccp_feat_default_send_ndp_count = DCCPF_INITIAL_SEND_NDP_COUNT;
+EXPORT_SYMBOL_GPL(dccp_feat_default_sequence_window);
+
void dccp_minisock_init(struct dccp_minisock *dmsk)
{
dmsk->dccpms_sequence_window = dccp_feat_default_sequence_window;
diff --git a/net/dccp/proto.c b/net/dccp/proto.c
index f4f0627ea41..6f14bb5a28d 100644
--- a/net/dccp/proto.c
+++ b/net/dccp/proto.c
@@ -484,7 +484,7 @@ static int do_dccp_setsockopt(struct sock *sk, int level, int optname,
err = -EINVAL;
else
err = dccp_setsockopt_change(sk, DCCPO_CHANGE_L,
- (struct dccp_so_feat *)
+ (struct dccp_so_feat __user *)
optval);
break;
@@ -493,7 +493,7 @@ static int do_dccp_setsockopt(struct sock *sk, int level, int optname,
err = -EINVAL;
else
err = dccp_setsockopt_change(sk, DCCPO_CHANGE_R,
- (struct dccp_so_feat *)
+ (struct dccp_so_feat __user *)
optval);
break;