From 3c6952624a8f600f9a0fbc1f5db5560a7ef9b13e Mon Sep 17 00:00:00 2001 From: Gerrit Renker Date: Wed, 15 Nov 2006 21:27:47 -0200 Subject: [DCCP]: Introduce DCCP_{BUG{_ON},CRIT} macros, use enum:8 for the ccid3 states This patch tackles the following problem: * the ccid3_hc_{t,r}x_sock define ccid3hc{t,r}x_state as `u8', but in reality there can only be a few, pre-defined enum names * this necessitates addiditional checking for unexpected values which would otherwise be caught by the compiler Signed-off-by: Gerrit Renker Signed-off-by: Arnaldo Carvalho de Melo --- net/dccp/ccids/ccid3.c | 45 ++++++++++++--------------------------------- net/dccp/ccids/ccid3.h | 19 +++++++++++++++++-- 2 files changed, 29 insertions(+), 35 deletions(-) (limited to 'net/dccp/ccids') diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c index cec23ad..2fa0c6d 100644 --- a/net/dccp/ccids/ccid3.c +++ b/net/dccp/ccids/ccid3.c @@ -75,14 +75,6 @@ static struct dccp_tx_hist *ccid3_tx_hist; static struct dccp_rx_hist *ccid3_rx_hist; static struct dccp_li_hist *ccid3_li_hist; -/* TFRC sender states */ -enum ccid3_hc_tx_states { - TFRC_SSTATE_NO_SENT = 1, - TFRC_SSTATE_NO_FBACK, - TFRC_SSTATE_FBACK, - TFRC_SSTATE_TERM, -}; - #ifdef CCID3_DEBUG static const char *ccid3_tx_state_name(enum ccid3_hc_tx_states state) { @@ -251,9 +243,8 @@ static void ccid3_hc_tx_no_feedback_timer(unsigned long data) hctx->ccid3hctx_x)); break; default: - printk(KERN_CRIT "%s: %s, sk=%p, Illegal state (%d)!\n", - __FUNCTION__, dccp_role(sk), sk, hctx->ccid3hctx_state); - dump_stack(); + DCCP_BUG("%s, sk=%p, Illegal state (%d)!", dccp_role(sk), sk, + hctx->ccid3hctx_state); goto out; } @@ -329,9 +320,8 @@ static int ccid3_hc_tx_send_packet(struct sock *sk, rc = delay > 0 ? delay : 0; break; default: - printk(KERN_CRIT "%s: %s, sk=%p, Illegal state (%d)!\n", - __FUNCTION__, dccp_role(sk), sk, hctx->ccid3hctx_state); - dump_stack(); + DCCP_BUG("%s, sk=%p, Illegal state (%d)!", dccp_role(sk), sk, + hctx->ccid3hctx_state); rc = -EINVAL; break; } @@ -423,9 +413,8 @@ static void ccid3_hc_tx_packet_sent(struct sock *sk, int more, int len) } break; default: - printk(KERN_CRIT "%s: %s, sk=%p, Illegal state (%d)!\n", - __FUNCTION__, dccp_role(sk), sk, hctx->ccid3hctx_state); - dump_stack(); + DCCP_BUG("%s, sk=%p, Illegal state (%d)!", dccp_role(sk), sk, + hctx->ccid3hctx_state); break; } } @@ -568,9 +557,8 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) hctx->ccid3hctx_idle = 1; break; default: - printk(KERN_CRIT "%s: %s, sk=%p, Illegal state (%d)!\n", - __FUNCTION__, dccp_role(sk), sk, hctx->ccid3hctx_state); - dump_stack(); + DCCP_BUG("%s, sk=%p, Illegal state (%d)!", dccp_role(sk), sk, + hctx->ccid3hctx_state); break; } } @@ -688,13 +676,6 @@ static void ccid3_hc_tx_exit(struct sock *sk) * RX Half Connection methods */ -/* TFRC receiver states */ -enum ccid3_hc_rx_states { - TFRC_RSTATE_NO_DATA = 1, - TFRC_RSTATE_DATA, - TFRC_RSTATE_TERM = 127, -}; - #ifdef CCID3_DEBUG static const char *ccid3_rx_state_name(enum ccid3_hc_rx_states state) { @@ -744,9 +725,8 @@ static void ccid3_hc_rx_send_feedback(struct sock *sk) } break; default: - printk(KERN_CRIT "%s: %s, sk=%p, Illegal state (%d)!\n", - __FUNCTION__, dccp_role(sk), sk, hcrx->ccid3hcrx_state); - dump_stack(); + DCCP_BUG("%s, sk=%p, Illegal state (%d)!", dccp_role(sk), sk, + hcrx->ccid3hcrx_state); return; } @@ -1088,9 +1068,8 @@ static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb) } return; default: - printk(KERN_CRIT "%s: %s, sk=%p, Illegal state (%d)!\n", - __FUNCTION__, dccp_role(sk), sk, hcrx->ccid3hcrx_state); - dump_stack(); + DCCP_BUG("%s, sk=%p, Illegal state (%d)!", dccp_role(sk), sk, + hcrx->ccid3hcrx_state); return; } diff --git a/net/dccp/ccids/ccid3.h b/net/dccp/ccids/ccid3.h index 0a2cb75..c122e75 100644 --- a/net/dccp/ccids/ccid3.h +++ b/net/dccp/ccids/ccid3.h @@ -73,6 +73,14 @@ struct ccid3_options_received { u32 ccid3or_receive_rate; }; +/* TFRC sender states */ +enum ccid3_hc_tx_states { + TFRC_SSTATE_NO_SENT = 1, + TFRC_SSTATE_NO_FBACK, + TFRC_SSTATE_FBACK, + TFRC_SSTATE_TERM, +}; + /** struct ccid3_hc_tx_sock - CCID3 sender half connection sock * * @ccid3hctx_state - Sender state @@ -103,7 +111,7 @@ struct ccid3_hc_tx_sock { #define ccid3hctx_t_rto ccid3hctx_tfrc.tfrctx_rto #define ccid3hctx_t_ipi ccid3hctx_tfrc.tfrctx_ipi u16 ccid3hctx_s; - u8 ccid3hctx_state; + enum ccid3_hc_tx_states ccid3hctx_state:8; u8 ccid3hctx_last_win_count; u8 ccid3hctx_idle; struct timeval ccid3hctx_t_last_win_count; @@ -115,6 +123,13 @@ struct ccid3_hc_tx_sock { struct ccid3_options_received ccid3hctx_options_received; }; +/* TFRC receiver states */ +enum ccid3_hc_rx_states { + TFRC_RSTATE_NO_DATA = 1, + TFRC_RSTATE_DATA, + TFRC_RSTATE_TERM = 127, +}; + struct ccid3_hc_rx_sock { struct tfrc_rx_info ccid3hcrx_tfrc; #define ccid3hcrx_x_recv ccid3hcrx_tfrc.tfrcrx_x_recv @@ -122,8 +137,8 @@ struct ccid3_hc_rx_sock { #define ccid3hcrx_p ccid3hcrx_tfrc.tfrcrx_p u64 ccid3hcrx_seqno_nonloss:48, ccid3hcrx_ccval_nonloss:4, - ccid3hcrx_state:8, 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; -- cgit v1.1 From 32aac18dfa0963fde40cc074ba97ebbae8b755f2 Mon Sep 17 00:00:00 2001 From: Andrea Bittau Date: Thu, 16 Nov 2006 14:28:40 -0200 Subject: [DCCP] CCID2: Code optimizations These are code optimizations which are relevant when dealing with large windows. They are not coded the way I would like to, but they do the job for the short-term. This patch should be more neat. Commiter note: Changed the seqno comparisions to use {after,before}48 to handle wrapping. Signed-off-by: Andrea Bittau Signed-off-by: Arnaldo Carvalho de Melo --- net/dccp/ccids/ccid2.c | 22 ++++++++++++++++++++-- net/dccp/ccids/ccid2.h | 1 + 2 files changed, 21 insertions(+), 2 deletions(-) (limited to 'net/dccp/ccids') diff --git a/net/dccp/ccids/ccid2.c b/net/dccp/ccids/ccid2.c index 162032b..6533cb2 100644 --- a/net/dccp/ccids/ccid2.c +++ b/net/dccp/ccids/ccid2.c @@ -619,7 +619,17 @@ static void ccid2_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) } ackno = DCCP_SKB_CB(skb)->dccpd_ack_seq; - seqp = hctx->ccid2hctx_seqh->ccid2s_prev; + if (after48(ackno, hctx->ccid2hctx_high_ack)) + hctx->ccid2hctx_high_ack = ackno; + + seqp = hctx->ccid2hctx_seqt; + while (before48(seqp->ccid2s_seq, ackno)) { + seqp = seqp->ccid2s_next; + if (seqp == hctx->ccid2hctx_seqh) { + seqp = hctx->ccid2hctx_seqh->ccid2s_prev; + break; + } + } /* If in slow-start, cwnd can increase at most Ack Ratio / 2 packets for * this single ack. I round up. @@ -697,7 +707,14 @@ static void ccid2_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) /* The state about what is acked should be correct now * Check for NUMDUPACK */ - seqp = hctx->ccid2hctx_seqh->ccid2s_prev; + seqp = hctx->ccid2hctx_seqt; + while (before48(seqp->ccid2s_seq, hctx->ccid2hctx_high_ack)) { + seqp = seqp->ccid2s_next; + if (seqp == hctx->ccid2hctx_seqh) { + seqp = hctx->ccid2hctx_seqh->ccid2s_prev; + break; + } + } done = 0; while (1) { if (seqp->ccid2s_acked) { @@ -771,6 +788,7 @@ static int ccid2_hc_tx_init(struct ccid *ccid, struct sock *sk) hctx->ccid2hctx_lastrtt = 0; hctx->ccid2hctx_rpdupack = -1; hctx->ccid2hctx_last_cong = jiffies; + hctx->ccid2hctx_high_ack = 0; hctx->ccid2hctx_rtotimer.function = &ccid2_hc_tx_rto_expire; hctx->ccid2hctx_rtotimer.data = (unsigned long)sk; diff --git a/net/dccp/ccids/ccid2.h b/net/dccp/ccids/ccid2.h index 5b2ef4a..a97a899 100644 --- a/net/dccp/ccids/ccid2.h +++ b/net/dccp/ccids/ccid2.h @@ -72,6 +72,7 @@ struct ccid2_hc_tx_sock { int ccid2hctx_rpdupack; int ccid2hctx_sendwait; unsigned long ccid2hctx_last_cong; + u64 ccid2hctx_high_ack; }; struct ccid2_hc_rx_sock { -- cgit v1.1 From 84116716cc9404356f775443b460f76766f08f65 Mon Sep 17 00:00:00 2001 From: Gerrit Renker Date: Mon, 20 Nov 2006 18:26:03 -0200 Subject: [DCCP]: enable debug messages also for static builds This patch * makes debugging (when configured) work both for static / module build * provides generic debugging macros for use in other DCCP / CCID modules * adds missing information about debug parameters to Kconfig * performs some code tidy-up Signed-off-by: Gerrit Renker Signed-off-by: Arnaldo Carvalho de Melo --- net/dccp/ccids/Kconfig | 14 ++++++++++++-- net/dccp/ccids/ccid2.c | 16 ++++++---------- 2 files changed, 18 insertions(+), 12 deletions(-) (limited to 'net/dccp/ccids') diff --git a/net/dccp/ccids/Kconfig b/net/dccp/ccids/Kconfig index 8533dab..ba826d9 100644 --- a/net/dccp/ccids/Kconfig +++ b/net/dccp/ccids/Kconfig @@ -28,13 +28,20 @@ config IP_DCCP_CCID2 This text was extracted from RFC 4340 (sec. 10.1), http://www.ietf.org/rfc/rfc4340.txt + To compile this CCID as a module, choose M here: the module will be + called dccp_ccid2. + If in doubt, say M. config IP_DCCP_CCID2_DEBUG - bool "CCID2 debug" + bool "CCID2 debugging messages" depends on IP_DCCP_CCID2 ---help--- - Enable CCID2 debug messages. + Enable CCID2-specific debugging messages. + + When compiling CCID2 as a module, this debugging output can + additionally be toggled by setting the ccid2_debug module + parameter to 0 or 1. If in doubt, say N. @@ -62,6 +69,9 @@ config IP_DCCP_CCID3 This text was extracted from RFC 4340 (sec. 10.2), http://www.ietf.org/rfc/rfc4340.txt + To compile this CCID as a module, choose M here: the module will be + called dccp_ccid3. + If in doubt, say M. config IP_DCCP_TFRC_LIB diff --git a/net/dccp/ccids/ccid2.c b/net/dccp/ccids/ccid2.c index 6533cb2..0fb0d66 100644 --- a/net/dccp/ccids/ccid2.c +++ b/net/dccp/ccids/ccid2.c @@ -33,18 +33,11 @@ #include "../dccp.h" #include "ccid2.h" -static int ccid2_debug; #ifdef CONFIG_IP_DCCP_CCID2_DEBUG -#define ccid2_pr_debug(format, a...) \ - do { if (ccid2_debug) \ - printk(KERN_DEBUG "%s: " format, __FUNCTION__, ##a); \ - } while (0) -#else -#define ccid2_pr_debug(format, a...) -#endif +static int ccid2_debug; +#define ccid2_pr_debug(format, a...) DCCP_PR_DEBUG(ccid2_debug, format, ##a) -#ifdef CONFIG_IP_DCCP_CCID2_DEBUG static void ccid2_hc_tx_check_sanity(const struct ccid2_hc_tx_sock *hctx) { int len = 0; @@ -86,7 +79,8 @@ static void ccid2_hc_tx_check_sanity(const struct ccid2_hc_tx_sock *hctx) BUG_ON(len != hctx->ccid2hctx_seqbufc * CCID2_SEQBUF_LEN); } #else -#define ccid2_hc_tx_check_sanity(hctx) do {} while (0) +#define ccid2_pr_debug(format, a...) +#define ccid2_hc_tx_check_sanity(hctx) #endif static int ccid2_hc_tx_alloc_seq(struct ccid2_hc_tx_sock *hctx, int num, @@ -841,8 +835,10 @@ static struct ccid_operations ccid2 = { .ccid_hc_rx_packet_recv = ccid2_hc_rx_packet_recv, }; +#ifdef CONFIG_IP_DCCP_CCID2_DEBUG module_param(ccid2_debug, int, 0444); MODULE_PARM_DESC(ccid2_debug, "Enable debug messages"); +#endif static __init int ccid2_module_init(void) { -- cgit v1.1 From 56724aa434e9b4d73548021ede7a1474f533f3fe Mon Sep 17 00:00:00 2001 From: Gerrit Renker Date: Mon, 20 Nov 2006 18:28:09 -0200 Subject: [DCCP]: Add CCID3 debug support to Kconfig This adds a CCID3 debug option to the configuration menu which is missing in Kconfig, but already used by the code. CCID 2 already provides such an entry. To enable debugging, set CONFIG_IP_DCCP_CCID3_DEBUG=y NOTE: The use of ccid3_{t,r}x_state_name is safe, since now only enum values can appear. Signed-off-by: Gerrit Renker Signed-off-by: Arnaldo Carvalho de Melo --- net/dccp/ccids/Kconfig | 11 +++++++++++ net/dccp/ccids/ccid3.c | 16 ++++++++-------- 2 files changed, 19 insertions(+), 8 deletions(-) (limited to 'net/dccp/ccids') diff --git a/net/dccp/ccids/Kconfig b/net/dccp/ccids/Kconfig index ba826d9..dac8916 100644 --- a/net/dccp/ccids/Kconfig +++ b/net/dccp/ccids/Kconfig @@ -78,4 +78,15 @@ config IP_DCCP_TFRC_LIB depends on IP_DCCP_CCID3 def_tristate IP_DCCP_CCID3 +config IP_DCCP_CCID3_DEBUG + bool "CCID3 debugging messages" + depends on IP_DCCP_CCID3 + ---help--- + Enable CCID3-specific debugging messages. + + When compiling CCID3 as a module, this debugging output can + additionally be toggled by setting the ccid3_debug module + parameter to 0 or 1. + + If in doubt, say N. endmenu diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c index 2fa0c6d..7db801e 100644 --- a/net/dccp/ccids/ccid3.c +++ b/net/dccp/ccids/ccid3.c @@ -60,13 +60,11 @@ static u32 usecs_div(const u32 a, const u32 b) return (b >= 2 * div) ? tmp / (b / div) : tmp; } -static int ccid3_debug; -#ifdef CCID3_DEBUG -#define ccid3_pr_debug(format, a...) \ - do { if (ccid3_debug) \ - printk(KERN_DEBUG "%s: " format, __FUNCTION__, ##a); \ - } while (0) + +#ifdef CONFIG_IP_DCCP_CCID3_DEBUG +static int ccid3_debug; +#define ccid3_pr_debug(format, a...) DCCP_PR_DEBUG(ccid3_debug, format, ##a) #else #define ccid3_pr_debug(format, a...) #endif @@ -75,7 +73,7 @@ static struct dccp_tx_hist *ccid3_tx_hist; static struct dccp_rx_hist *ccid3_rx_hist; static struct dccp_li_hist *ccid3_li_hist; -#ifdef CCID3_DEBUG +#ifdef CONFIG_IP_DCCP_CCID3_DEBUG static const char *ccid3_tx_state_name(enum ccid3_hc_tx_states state) { static char *ccid3_state_names[] = { @@ -676,7 +674,7 @@ static void ccid3_hc_tx_exit(struct sock *sk) * RX Half Connection methods */ -#ifdef CCID3_DEBUG +#ifdef CONFIG_IP_DCCP_CCID3_DEBUG static const char *ccid3_rx_state_name(enum ccid3_hc_rx_states state) { static char *ccid3_rx_state_names[] = { @@ -1240,8 +1238,10 @@ static struct ccid_operations ccid3 = { .ccid_hc_tx_getsockopt = ccid3_hc_tx_getsockopt, }; +#ifdef CONFIG_IP_DCCP_CCID3_DEBUG module_param(ccid3_debug, int, 0444); MODULE_PARM_DESC(ccid3_debug, "Enable debug messages"); +#endif static __init int ccid3_module_init(void) { -- cgit v1.1 From 59348b19efebfd6a8d0791ff81d207b16594c94b Mon Sep 17 00:00:00 2001 From: Gerrit Renker Date: Mon, 20 Nov 2006 18:39:23 -0200 Subject: [DCCP]: Simplified conditions due to use of enum:8 states This reaps the benefit of the earlier patch, which changed the type of CCID 3 states to use enums, in that many conditions are now simplified and the number of possible (unexpected) values is greatly reduced. In a few instances, this also allowed to simplify pre-conditions; where care has been taken to retain logical equivalence. [DCCP]: Introduce a consistent BUG/WARN message scheme This refines the existing set of DCCP messages so that * BUG(), BUG_ON(), WARN_ON() have meaningful DCCP-specific counterparts * DCCP_CRIT (for severe warnings) is not rate-limited * DCCP_WARN() is introduced as rate-limited wrapper Using these allows a faster and cleaner transition to their original counterparts once the code has matured into a full DCCP implementation. Signed-off-by: Gerrit Renker Signed-off-by: Arnaldo Carvalho de Melo --- net/dccp/ccids/ccid2.c | 2 +- net/dccp/ccids/ccid3.c | 132 ++++++++++++++++--------------------- net/dccp/ccids/lib/loss_interval.c | 6 +- net/dccp/ccids/lib/tfrc_equation.c | 7 +- 4 files changed, 63 insertions(+), 84 deletions(-) (limited to 'net/dccp/ccids') diff --git a/net/dccp/ccids/ccid2.c b/net/dccp/ccids/ccid2.c index 0fb0d66..207f7f9 100644 --- a/net/dccp/ccids/ccid2.c +++ b/net/dccp/ccids/ccid2.c @@ -420,7 +420,7 @@ static int ccid2_ackvector(struct sock *sk, struct sk_buff *skb, int offset, return -1; out_invalid_option: - BUG_ON(1); /* should never happen... options were previously parsed ! */ + DCCP_BUG("Invalid option - this should not happen (previous parsing)!"); return -1; } diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c index 7db801e..4eada51 100644 --- a/net/dccp/ccids/ccid3.c +++ b/net/dccp/ccids/ccid3.c @@ -176,8 +176,6 @@ static void ccid3_hc_tx_no_feedback_timer(unsigned long data) ccid3_tx_state_name(hctx->ccid3hctx_state)); switch (hctx->ccid3hctx_state) { - case TFRC_SSTATE_TERM: - goto out; case TFRC_SSTATE_NO_FBACK: /* Halve send rate */ hctx->ccid3hctx_x /= 2; @@ -240,9 +238,10 @@ static void ccid3_hc_tx_no_feedback_timer(unsigned long data) 2 * usecs_div(hctx->ccid3hctx_s, hctx->ccid3hctx_x)); break; - default: - DCCP_BUG("%s, sk=%p, Illegal state (%d)!", dccp_role(sk), sk, - hctx->ccid3hctx_state); + case TFRC_SSTATE_NO_SENT: + DCCP_BUG("Illegal %s state NO_SENT, sk=%p", dccp_role(sk), sk); + /* fall through */ + case TFRC_SSTATE_TERM: goto out; } @@ -264,7 +263,7 @@ static int ccid3_hc_tx_send_packet(struct sock *sk, long delay; int rc = -ENOTCONN; - BUG_ON(hctx == NULL || hctx->ccid3hctx_state == TFRC_SSTATE_TERM); + BUG_ON(hctx == NULL); /* Check if pure ACK or Terminating*/ /* @@ -282,9 +281,8 @@ static int ccid3_hc_tx_send_packet(struct sock *sk, rc = -ENOBUFS; if (unlikely(new_packet == NULL)) { - LIMIT_NETDEBUG(KERN_WARNING "%s: %s, sk=%p, not enough " - "mem to add to history, send refused\n", - __FUNCTION__, dccp_role(sk), sk); + DCCP_WARN("%s, sk=%p, not enough mem to add to history," + "send refused\n", dccp_role(sk), sk); goto out; } @@ -317,9 +315,8 @@ static int ccid3_hc_tx_send_packet(struct sock *sk, /* divide by -1000 is to convert to ms and get sign right */ rc = delay > 0 ? delay : 0; break; - default: - DCCP_BUG("%s, sk=%p, Illegal state (%d)!", dccp_role(sk), sk, - hctx->ccid3hctx_state); + case TFRC_SSTATE_TERM: + DCCP_BUG("Illegal %s state TERM, sk=%p", dccp_role(sk), sk); rc = -EINVAL; break; } @@ -343,7 +340,7 @@ static void ccid3_hc_tx_packet_sent(struct sock *sk, int more, int len) struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk); struct timeval now; - BUG_ON(hctx == NULL || hctx->ccid3hctx_state == TFRC_SSTATE_TERM); + BUG_ON(hctx == NULL); dccp_timestamp(sk, &now); @@ -354,13 +351,11 @@ static void ccid3_hc_tx_packet_sent(struct sock *sk, int more, int len) packet = dccp_tx_hist_head(&hctx->ccid3hctx_hist); if (unlikely(packet == NULL)) { - LIMIT_NETDEBUG(KERN_WARNING "%s: packet doesn't " - "exists in history!\n", __FUNCTION__); + DCCP_WARN("packet doesn't exist in history!\n"); return; } if (unlikely(packet->dccphtx_sent)) { - LIMIT_NETDEBUG(KERN_WARNING "%s: no unsent packet in " - "history!\n", __FUNCTION__); + DCCP_WARN("no unsent packet in history!\n"); return; } packet->dccphtx_tstamp = now; @@ -395,9 +390,8 @@ static void ccid3_hc_tx_packet_sent(struct sock *sk, int more, int len) case TFRC_SSTATE_NO_SENT: /* if first wasn't pure ack */ if (len != 0) - printk(KERN_CRIT "%s: %s, First packet sent is noted " - "as a data packet\n", - __FUNCTION__, dccp_role(sk)); + DCCP_CRIT("%s, First packet sent is noted " + "as a data packet", dccp_role(sk)); return; case TFRC_SSTATE_NO_FBACK: case TFRC_SSTATE_FBACK: @@ -410,9 +404,8 @@ static void ccid3_hc_tx_packet_sent(struct sock *sk, int more, int len) hctx->ccid3hctx_t_ipi); } break; - default: - DCCP_BUG("%s, sk=%p, Illegal state (%d)!", dccp_role(sk), sk, - hctx->ccid3hctx_state); + case TFRC_SSTATE_TERM: + DCCP_BUG("Illegal %s state TERM, sk=%p", dccp_role(sk), sk); break; } } @@ -430,7 +423,7 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) u32 x_recv; u32 r_sample; - BUG_ON(hctx == NULL || hctx->ccid3hctx_state == TFRC_SSTATE_TERM); + BUG_ON(hctx == NULL); /* we are only interested in ACKs */ if (!(DCCP_SKB_CB(skb)->dccpd_type == DCCP_PKT_ACK || @@ -455,11 +448,10 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) packet = dccp_tx_hist_find_entry(&hctx->ccid3hctx_hist, DCCP_SKB_CB(skb)->dccpd_ack_seq); if (unlikely(packet == NULL)) { - LIMIT_NETDEBUG(KERN_WARNING "%s: %s, sk=%p, seqno " - "%llu(%s) does't exist in history!\n", - __FUNCTION__, dccp_role(sk), sk, + DCCP_WARN("%s, sk=%p, seqno %llu(%s) does't exist " + "in history!\n", dccp_role(sk), sk, (unsigned long long)DCCP_SKB_CB(skb)->dccpd_ack_seq, - dccp_packet_name(DCCP_SKB_CB(skb)->dccpd_type)); + dccp_packet_name(DCCP_SKB_CB(skb)->dccpd_type)); return; } @@ -467,9 +459,8 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) dccp_timestamp(sk, &now); r_sample = timeval_delta(&now, &packet->dccphtx_tstamp); if (unlikely(r_sample <= t_elapsed)) - LIMIT_NETDEBUG(KERN_WARNING "%s: r_sample=%uus, " - "t_elapsed=%uus\n", - __FUNCTION__, r_sample, t_elapsed); + DCCP_WARN("r_sample=%uus,t_elapsed=%uus\n", + r_sample, t_elapsed); else r_sample -= t_elapsed; @@ -554,9 +545,8 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) /* set idle flag */ hctx->ccid3hctx_idle = 1; break; - default: - DCCP_BUG("%s, sk=%p, Illegal state (%d)!", dccp_role(sk), sk, - hctx->ccid3hctx_state); + case TFRC_SSTATE_TERM: + DCCP_BUG("Illegal %s state TERM, sk=%p", dccp_role(sk), sk); break; } } @@ -596,9 +586,9 @@ static int ccid3_hc_tx_parse_options(struct sock *sk, unsigned char option, switch (option) { case TFRC_OPT_LOSS_EVENT_RATE: if (unlikely(len != 4)) { - LIMIT_NETDEBUG(KERN_WARNING "%s: %s, sk=%p, invalid " - "len for TFRC_OPT_LOSS_EVENT_RATE\n", - __FUNCTION__, dccp_role(sk), sk); + DCCP_WARN("%s, sk=%p, invalid len %d " + "for TFRC_OPT_LOSS_EVENT_RATE\n", + dccp_role(sk), sk, len); rc = -EINVAL; } else { opt_recv->ccid3or_loss_event_rate = ntohl(*(__be32 *)value); @@ -617,9 +607,9 @@ static int ccid3_hc_tx_parse_options(struct sock *sk, unsigned char option, break; case TFRC_OPT_RECEIVE_RATE: if (unlikely(len != 4)) { - LIMIT_NETDEBUG(KERN_WARNING "%s: %s, sk=%p, invalid " - "len for TFRC_OPT_RECEIVE_RATE\n", - __FUNCTION__, dccp_role(sk), sk); + DCCP_WARN("%s, sk=%p, invalid len %d " + "for TFRC_OPT_RECEIVE_RATE\n", + dccp_role(sk), sk, len); rc = -EINVAL; } else { opt_recv->ccid3or_receive_rate = ntohl(*(__be32 *)value); @@ -722,17 +712,15 @@ static void ccid3_hc_rx_send_feedback(struct sock *sk) delta); } break; - default: - DCCP_BUG("%s, sk=%p, Illegal state (%d)!", dccp_role(sk), sk, - hcrx->ccid3hcrx_state); + case TFRC_RSTATE_TERM: + DCCP_BUG("Illegal %s state TERM, sk=%p", dccp_role(sk), sk); return; } packet = dccp_rx_hist_find_data_packet(&hcrx->ccid3hcrx_hist); if (unlikely(packet == NULL)) { - LIMIT_NETDEBUG(KERN_WARNING "%s: %s, sk=%p, no data packet " - "in history!\n", - __FUNCTION__, dccp_role(sk), sk); + DCCP_WARN("%s, sk=%p, no data packet in history!\n", + dccp_role(sk), sk); return; } @@ -820,29 +808,29 @@ static u32 ccid3_hc_rx_calc_first_li(struct sock *sk) } if (unlikely(step == 0)) { - LIMIT_NETDEBUG(KERN_WARNING "%s: %s, sk=%p, packet history " - "contains no data packets!\n", - __FUNCTION__, dccp_role(sk), sk); + DCCP_WARN("%s, sk=%p, packet history has no data packets!\n", + dccp_role(sk), sk); return ~0; } if (unlikely(interval == 0)) { - LIMIT_NETDEBUG(KERN_WARNING "%s: %s, sk=%p, Could not find a " - "win_count interval > 0. Defaulting to 1\n", - __FUNCTION__, dccp_role(sk), sk); + DCCP_WARN("%s, sk=%p, Could not find a win_count interval > 0." + "Defaulting to 1\n", dccp_role(sk), sk); interval = 1; } found: if (!tail) { - LIMIT_NETDEBUG(KERN_WARNING "%s: tail is null\n", - __FUNCTION__); + DCCP_CRIT("tail is null\n"); 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); - if (rtt == 0) - rtt = 1; + + if (rtt == 0) { + DCCP_WARN("RTT==0, setting to 1\n"); + rtt = 1; + } dccp_timestamp(sk, &tstamp); delta = timeval_delta(&tstamp, &hcrx->ccid3hcrx_tstamp_last_feedback); @@ -856,9 +844,7 @@ found: tmp2 = (u32)tmp1; if (!tmp2) { - LIMIT_NETDEBUG(KERN_WARNING "tmp2 = 0 " - "%s: x_recv = %u, rtt =%u\n", - __FUNCTION__, x_recv, rtt); + DCCP_CRIT("tmp2 = 0, x_recv = %u, rtt =%u\n", x_recv, rtt); return ~0; } @@ -904,8 +890,7 @@ static void ccid3_hc_rx_update_li(struct sock *sk, u64 seq_loss, u8 win_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(); + DCCP_BUG("out of memory - can not allocate entry"); return; } @@ -984,9 +969,7 @@ static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb) u32 p_prev, rtt_prev, r_sample, t_elapsed; int loss; - BUG_ON(hcrx == NULL || - !(hcrx->ccid3hcrx_state == TFRC_RSTATE_NO_DATA || - hcrx->ccid3hcrx_state == TFRC_RSTATE_DATA)); + BUG_ON(hcrx == NULL); opt_recv = &dccp_sk(sk)->dccps_options_received; @@ -1004,9 +987,8 @@ static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb) 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); + DCCP_WARN("r_sample=%uus, t_elapsed=%uus\n", + r_sample, t_elapsed); else r_sample -= t_elapsed; @@ -1030,9 +1012,8 @@ static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb) packet = dccp_rx_hist_entry_new(ccid3_rx_hist, sk, opt_recv->dccpor_ndp, skb, SLAB_ATOMIC); if (unlikely(packet == NULL)) { - LIMIT_NETDEBUG(KERN_WARNING "%s: %s, sk=%p, Not enough mem to " - "add rx packet to history, consider it lost!\n", - __FUNCTION__, dccp_role(sk), sk); + DCCP_WARN("%s, sk=%p, Not enough mem to add rx packet " + "to history, consider it lost!\n", dccp_role(sk), sk); return; } @@ -1065,9 +1046,8 @@ static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb) ccid3_hc_rx_send_feedback(sk); } return; - default: - DCCP_BUG("%s, sk=%p, Illegal state (%d)!", dccp_role(sk), sk, - hcrx->ccid3hcrx_state); + case TFRC_RSTATE_TERM: + DCCP_BUG("Illegal %s state TERM, sk=%p", dccp_role(sk), sk); return; } @@ -1084,10 +1064,8 @@ 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(); - } + } else + DCCP_BUG("empty loss history"); if (hcrx->ccid3hcrx_p > p_prev) { ccid3_hc_rx_send_feedback(sk); diff --git a/net/dccp/ccids/lib/loss_interval.c b/net/dccp/ccids/lib/loss_interval.c index 906c81a..48b9b93 100644 --- a/net/dccp/ccids/lib/loss_interval.c +++ b/net/dccp/ccids/lib/loss_interval.c @@ -13,7 +13,7 @@ #include #include - +#include "../../dccp.h" #include "loss_interval.h" struct dccp_li_hist *dccp_li_hist_new(const char *name) @@ -109,7 +109,7 @@ u32 dccp_li_hist_calc_i_mean(struct list_head *list) i_tot = max(i_tot0, i_tot1); if (!w_tot) { - LIMIT_NETDEBUG(KERN_WARNING "%s: w_tot = 0\n", __FUNCTION__); + DCCP_WARN("w_tot = 0\n"); return 1; } @@ -128,7 +128,7 @@ int dccp_li_hist_interval_new(struct dccp_li_hist *hist, entry = dccp_li_hist_entry_new(hist, SLAB_ATOMIC); if (entry == NULL) { dccp_li_hist_purge(hist, list); - dump_stack(); + DCCP_BUG("loss interval list entry is NULL"); return 0; } entry->dccplih_interval = ~0; diff --git a/net/dccp/ccids/lib/tfrc_equation.c b/net/dccp/ccids/lib/tfrc_equation.c index 44076e0..2601012 100644 --- a/net/dccp/ccids/lib/tfrc_equation.c +++ b/net/dccp/ccids/lib/tfrc_equation.c @@ -13,9 +13,8 @@ */ #include - #include - +#include "../../dccp.h" #include "tfrc.h" #define TFRC_CALC_X_ARRSIZE 500 @@ -588,8 +587,10 @@ u32 tfrc_calc_x(u16 s, u32 R, u32 p) /* p should be 0 unless there is a bug in my code */ index = 0; - if (R == 0) + if (R == 0) { + DCCP_WARN("RTT==0, setting to 1\n"); R = 1; /* RTT can't be zero or else divide by zero */ + } BUG_ON(index >= TFRC_CALC_X_ARRSIZE); -- cgit v1.1 From 23ea8945f6be2287fec67c85abcf24736c1ded80 Mon Sep 17 00:00:00 2001 From: Gerrit Renker Date: Mon, 20 Nov 2006 18:40:42 -0200 Subject: [CCID 3]: Add annotations for socket structures This adds documentation to the CCID 3 rx/tx socket fields, plus some minor re-formatting. Signed-off-by: Gerrit Renker Signed-off-by: Arnaldo Carvalho de Melo --- net/dccp/ccids/ccid3.h | 90 ++++++++++++++++++++++++++++++-------------------- 1 file changed, 55 insertions(+), 35 deletions(-) (limited to 'net/dccp/ccids') diff --git a/net/dccp/ccids/ccid3.h b/net/dccp/ccids/ccid3.h index c122e75..e2e43c1 100644 --- a/net/dccp/ccids/ccid3.h +++ b/net/dccp/ccids/ccid3.h @@ -81,26 +81,28 @@ enum ccid3_hc_tx_states { TFRC_SSTATE_TERM, }; -/** struct ccid3_hc_tx_sock - CCID3 sender half connection sock +/** struct ccid3_hc_tx_sock - CCID3 sender half-connection socket * - * @ccid3hctx_state - Sender state - * @ccid3hctx_x - Current sending rate - * @ccid3hctx_x_recv - Receive rate - * @ccid3hctx_x_calc - Calculated send (?) rate - * @ccid3hctx_s - Packet size - * @ccid3hctx_rtt - Estimate of current round trip time in usecs - * @@ccid3hctx_p - Current loss event rate (0-1) scaled by 1000000 - * @ccid3hctx_last_win_count - Last window counter sent - * @ccid3hctx_t_last_win_count - Timestamp of earliest packet - * with last_win_count value sent - * @ccid3hctx_no_feedback_timer - Handle to no feedback timer - * @ccid3hctx_idle - FIXME - * @ccid3hctx_t_ld - Time last doubled during slow start - * @ccid3hctx_t_nom - Nominal send time of next packet - * @ccid3hctx_t_ipi - Interpacket (send) interval - * @ccid3hctx_delta - Send timer delta - * @ccid3hctx_hist - Packet history - */ + * @ccid3hctx_x - Current sending rate + * @ccid3hctx_x_recv - Receive rate + * @ccid3hctx_x_calc - Calculated send rate (RFC 3448, 3.1) + * @ccid3hctx_rtt - Estimate of current round trip time in usecs + * @ccid3hctx_p - Current loss event rate (0-1) scaled by 1000000 + * @ccid3hctx_s - Packet size + * @ccid3hctx_t_rto - Retransmission Timeout (RFC 3448, 3.1) + * @ccid3hctx_t_ipi - Interpacket (send) interval (RFC 3448, 4.6) + * @ccid3hctx_state - Sender state, one of %ccid3_hc_tx_states + * @ccid3hctx_last_win_count - Last window counter sent + * @ccid3hctx_t_last_win_count - Timestamp of earliest packet + * with last_win_count value sent + * @ccid3hctx_no_feedback_timer - Handle to no feedback timer + * @ccid3hctx_idle - Flag indicating that sender is idling + * @ccid3hctx_t_ld - Time last doubled during slow start + * @ccid3hctx_t_nom - Nominal send time of next packet + * @ccid3hctx_delta - Send timer delta + * @ccid3hctx_hist - Packet history + * @ccid3hctx_options_received - Parsed set of retrieved options + */ struct ccid3_hc_tx_sock { struct tfrc_tx_info ccid3hctx_tfrc; #define ccid3hctx_x ccid3hctx_tfrc.tfrctx_x @@ -130,23 +132,41 @@ enum ccid3_hc_rx_states { TFRC_RSTATE_TERM = 127, }; +/** struct ccid3_hc_rx_sock - CCID3 receiver half-connection socket + * + * @ccid3hcrx_x_recv - Receiver estimate of send rate (RFC 3448 4.3) + * @ccid3hcrx_rtt - Receiver estimate of rtt (non-standard) + * @ccid3hcrx_p - current loss event rate (RFC 3448 5.4) + * @ccid3hcrx_seqno_nonloss - Last received non-loss sequence number + * @ccid3hcrx_ccval_nonloss - Last received non-loss Window CCVal + * @ccid3hcrx_ccval_last_counter - Tracks window counter (RFC 4342, 8.1) + * @ccid3hcrx_state - receiver state, one of %ccid3_hc_rx_states + * @ccid3hcrx_bytes_recv - Total sum of DCCP payload bytes + * @ccid3hcrx_tstamp_last_feedback - Time at which last feedback was sent + * @ccid3hcrx_tstamp_last_ack - Time at which last feedback was sent + * @ccid3hcrx_hist - Packet history + * @ccid3hcrx_li_hist - Loss Interval History + * @ccid3hcrx_s - Received packet size in bytes + * @ccid3hcrx_pinv - Inverse of Loss Event Rate (RFC 4342, sec. 8.5) + * @ccid3hcrx_elapsed_time - Time since packet reception + */ struct ccid3_hc_rx_sock { - struct tfrc_rx_info ccid3hcrx_tfrc; -#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_nonloss:48, - ccid3hcrx_ccval_nonloss:4, - 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; - struct list_head ccid3hcrx_hist; - struct list_head ccid3hcrx_li_hist; - u16 ccid3hcrx_s; - u32 ccid3hcrx_pinv; - u32 ccid3hcrx_elapsed_time; + struct tfrc_rx_info ccid3hcrx_tfrc; +#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_nonloss:48, + ccid3hcrx_ccval_nonloss:4, + 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; + struct list_head ccid3hcrx_hist; + struct list_head ccid3hcrx_li_hist; + u16 ccid3hcrx_s; + u32 ccid3hcrx_pinv; + u32 ccid3hcrx_elapsed_time; }; static inline struct ccid3_hc_tx_sock *ccid3_hc_tx_sk(const struct sock *sk) -- cgit v1.1 From 455431739ca2f4c7f02d0a5979559ac5a68a6f95 Mon Sep 17 00:00:00 2001 From: Ian McDonald Date: Mon, 20 Nov 2006 18:44:03 -0200 Subject: [DCCP] CCID3: Remove non-referenced variable This removes a non-referenced variable. Signed-off-by: Ian McDonald Signed-off-by: Arnaldo Carvalho de Melo --- net/dccp/ccids/ccid3.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'net/dccp/ccids') diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c index 4eada51..fb21f2d 100644 --- a/net/dccp/ccids/ccid3.c +++ b/net/dccp/ccids/ccid3.c @@ -965,7 +965,6 @@ static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb) const struct dccp_options_received *opt_recv; struct dccp_rx_hist_entry *packet; struct timeval now; - u8 win_count; u32 p_prev, rtt_prev, r_sample, t_elapsed; int loss; @@ -1017,8 +1016,6 @@ static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb) return; } - win_count = packet->dccphrx_ccval; - loss = ccid3_hc_rx_detect_loss(sk, packet); if (DCCP_SKB_CB(skb)->dccpd_type == DCCP_PKT_ACK) -- cgit v1.1 From 6472c051fcc5e571a9abee7f7a1ac58cc6e7bafa Mon Sep 17 00:00:00 2001 From: Andrea Bittau Date: Sun, 26 Nov 2006 01:07:50 -0200 Subject: [DCCP] ccid2: Allow window to grow larger Now that we can stuff bigger ack vectors into options. Signed-off-by: Andrea Bittau Signed-off-by: Arnaldo Carvalho de Melo --- net/dccp/ccids/ccid2.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net/dccp/ccids') diff --git a/net/dccp/ccids/ccid2.h b/net/dccp/ccids/ccid2.h index a97a899..ebd7949 100644 --- a/net/dccp/ccids/ccid2.h +++ b/net/dccp/ccids/ccid2.h @@ -35,7 +35,7 @@ struct ccid2_seq { struct ccid2_seq *ccid2s_next; }; -#define CCID2_SEQBUF_LEN 256 +#define CCID2_SEQBUF_LEN 1024 #define CCID2_SEQBUF_MAX 128 /** struct ccid2_hc_tx_sock - CCID2 TX half connection -- cgit v1.1 From 90feeb951f61a80d3a8f8e5ced25b9ec78867eaf Mon Sep 17 00:00:00 2001 From: Gerrit Renker Date: Mon, 27 Nov 2006 12:13:38 -0200 Subject: [DCCP] ccid3: Fix bug in calculation of first t_nom and first t_ipi Problem: --- net/dccp/ccids/ccid3.c | 11 ++++++----- net/dccp/ccids/ccid3.h | 2 -- 2 files changed, 6 insertions(+), 7 deletions(-) (limited to 'net/dccp/ccids') diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c index fb21f2d..d7b688e 100644 --- a/net/dccp/ccids/ccid3.c +++ b/net/dccp/ccids/ccid3.c @@ -298,13 +298,14 @@ static int ccid3_hc_tx_send_packet(struct sock *sk, hctx->ccid3hctx_last_win_count = 0; hctx->ccid3hctx_t_last_win_count = now; ccid3_hc_tx_set_state(sk, TFRC_SSTATE_NO_FBACK); - hctx->ccid3hctx_t_ipi = TFRC_INITIAL_IPI; - /* Set nominal send time for initial packet */ + /* First timeout, according to [RFC 3448, 4.2], is 1 second */ + hctx->ccid3hctx_t_ipi = USEC_PER_SEC; + /* Initial delta: minimum of 0.5 sec and t_gran/2 */ + hctx->ccid3hctx_delta = TFRC_OPSYS_HALF_TIME_GRAN; + + /* Set t_0 for initial packet */ hctx->ccid3hctx_t_nom = now; - timeval_add_usecs(&hctx->ccid3hctx_t_nom, - hctx->ccid3hctx_t_ipi); - ccid3_calc_new_delta(hctx); rc = 0; break; case TFRC_SSTATE_NO_FBACK: diff --git a/net/dccp/ccids/ccid3.h b/net/dccp/ccids/ccid3.h index e2e43c1..4621652 100644 --- a/net/dccp/ccids/ccid3.h +++ b/net/dccp/ccids/ccid3.h @@ -49,8 +49,6 @@ /* Two seconds as per CCID3 spec */ #define TFRC_INITIAL_TIMEOUT (2 * USEC_PER_SEC) -#define TFRC_INITIAL_IPI (USEC_PER_SEC / 4) - /* In usecs - half the scheduling granularity as per RFC3448 4.6 */ #define TFRC_OPSYS_HALF_TIME_GRAN (USEC_PER_SEC / (2 * HZ)) -- cgit v1.1 From f5c2d6367b04fd5ba98a5f9846b5fb870423968a Mon Sep 17 00:00:00 2001 From: Gerrit Renker Date: Mon, 27 Nov 2006 12:22:48 -0200 Subject: [DCCP] ccid3: Simplify control flow in the calculation of t_ipi This patch performs a simplifying (performance) optimisation: In each call of the inline function ccid3_calc_new_t_ipi(), the state is tested against TFRC_SSTATE_NO_FBACK. This is expensive when the function is called very often. A simpler solution, implemented by this patch, is to adapt the control flow. Background: --- net/dccp/ccids/ccid3.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) (limited to 'net/dccp/ccids') diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c index d7b688e..df88c54b 100644 --- a/net/dccp/ccids/ccid3.c +++ b/net/dccp/ccids/ccid3.c @@ -103,13 +103,7 @@ static void ccid3_hc_tx_set_state(struct sock *sk, /* Calculate new t_ipi (inter packet interval) by t_ipi = s / X_inst */ static inline void ccid3_calc_new_t_ipi(struct ccid3_hc_tx_sock *hctx) { - /* - * If no feedback spec says t_ipi is 1 second (set elsewhere and then - * doubles after every no feedback timer (separate function) - */ - if (hctx->ccid3hctx_state != TFRC_SSTATE_NO_FBACK) - hctx->ccid3hctx_t_ipi = usecs_div(hctx->ccid3hctx_s, - hctx->ccid3hctx_x); + hctx->ccid3hctx_t_ipi = usecs_div(hctx->ccid3hctx_s, hctx->ccid3hctx_x); } /* Calculate new delta by delta = min(t_ipi / 2, t_gran / 2) */ @@ -395,6 +389,8 @@ static void ccid3_hc_tx_packet_sent(struct sock *sk, int more, int len) "as a data packet", dccp_role(sk)); return; case TFRC_SSTATE_NO_FBACK: + /* t_nom, t_ipi, delta do not change until feedback arrives */ + return; case TFRC_SSTATE_FBACK: if (len > 0) { timeval_sub_usecs(&hctx->ccid3hctx_t_nom, -- cgit v1.1 From 91cf5a17257e1d2ef936fbf0223c3436ca583af9 Mon Sep 17 00:00:00 2001 From: Gerrit Renker Date: Mon, 27 Nov 2006 12:25:10 -0200 Subject: [DCCP] ccid3: Fix calculation of t_ipi time of scheduled transmission Problem: --- net/dccp/ccids/ccid3.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) (limited to 'net/dccp/ccids') diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c index df88c54b..fb1a5e8 100644 --- a/net/dccp/ccids/ccid3.c +++ b/net/dccp/ccids/ccid3.c @@ -304,11 +304,19 @@ static int ccid3_hc_tx_send_packet(struct sock *sk, break; case TFRC_SSTATE_NO_FBACK: case TFRC_SSTATE_FBACK: - delay = (timeval_delta(&now, &hctx->ccid3hctx_t_nom) - - hctx->ccid3hctx_delta); - delay /= -1000; - /* divide by -1000 is to convert to ms and get sign right */ - rc = delay > 0 ? delay : 0; + delay = timeval_delta(&hctx->ccid3hctx_t_nom, &now); + /* + * Scheduling of packet transmissions [RFC 3448, 4.6] + * + * if (t_now > t_nom - delta) + * // send the packet now + * else + * // send the packet in (t_nom - t_now) milliseconds. + */ + if (delay < hctx->ccid3hctx_delta) + rc = 0; + else + rc = delay/1000L; break; case TFRC_SSTATE_TERM: DCCP_BUG("Illegal %s state TERM, sk=%p", dccp_role(sk), sk); -- cgit v1.1 From 7da7f456d7bc0e52009f882e8af0ac910293e157 Mon Sep 17 00:00:00 2001 From: Gerrit Renker Date: Mon, 27 Nov 2006 12:26:03 -0200 Subject: [DCCP] ccid3: Simplify control flow of ccid3_hc_tx_send_packet This makes some logically equivalent simplifications, by replacing rc - values plus goto's with direct return statements. Signed-off-by: Gerrit Renker Signed-off-by: Ian McDonald Signed-off-by: Arnaldo Carvalho de Melo --- net/dccp/ccids/ccid3.c | 40 ++++++++++++++++++---------------------- 1 file changed, 18 insertions(+), 22 deletions(-) (limited to 'net/dccp/ccids') diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c index fb1a5e8..2745d83 100644 --- a/net/dccp/ccids/ccid3.c +++ b/net/dccp/ccids/ccid3.c @@ -247,6 +247,12 @@ out: sock_put(sk); } +/* + * returns + * > 0: delay (in msecs) that should pass before actually sending + * = 0: can send immediately + * < 0: error condition; do not send packet + */ static int ccid3_hc_tx_send_packet(struct sock *sk, struct sk_buff *skb, int len) { @@ -255,7 +261,6 @@ static int ccid3_hc_tx_send_packet(struct sock *sk, struct dccp_tx_hist_entry *new_packet; struct timeval now; long delay; - int rc = -ENOTCONN; BUG_ON(hctx == NULL); @@ -265,7 +270,7 @@ static int ccid3_hc_tx_send_packet(struct sock *sk, * packets can have zero length, but why the comment about "pure ACK"? */ if (unlikely(len == 0)) - goto out; + return -ENOTCONN; /* See if last packet allocated was not sent */ new_packet = dccp_tx_hist_head(&hctx->ccid3hctx_hist); @@ -273,11 +278,10 @@ static int ccid3_hc_tx_send_packet(struct sock *sk, new_packet = dccp_tx_hist_entry_new(ccid3_tx_hist, SLAB_ATOMIC); - rc = -ENOBUFS; if (unlikely(new_packet == NULL)) { DCCP_WARN("%s, sk=%p, not enough mem to add to history," "send refused\n", dccp_role(sk), sk); - goto out; + return -ENOBUFS; } dccp_tx_hist_add_entry(&hctx->ccid3hctx_hist, new_packet); @@ -300,7 +304,6 @@ static int ccid3_hc_tx_send_packet(struct sock *sk, /* Set t_0 for initial packet */ hctx->ccid3hctx_t_nom = now; - rc = 0; break; case TFRC_SSTATE_NO_FBACK: case TFRC_SSTATE_FBACK: @@ -313,28 +316,21 @@ static int ccid3_hc_tx_send_packet(struct sock *sk, * else * // send the packet in (t_nom - t_now) milliseconds. */ - if (delay < hctx->ccid3hctx_delta) - rc = 0; - else - rc = delay/1000L; + if (delay >= hctx->ccid3hctx_delta) + return delay / 1000L; break; case TFRC_SSTATE_TERM: DCCP_BUG("Illegal %s state TERM, sk=%p", dccp_role(sk), sk); - rc = -EINVAL; - break; + return -EINVAL; } - /* Can we send? if so add options and add to packet history */ - if (rc == 0) { - dp->dccps_hc_tx_insert_options = 1; - 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; + /* prepare to send now (add options etc.) */ + dp->dccps_hc_tx_insert_options = 1; + 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); + + return 0; } static void ccid3_hc_tx_packet_sent(struct sock *sk, int more, int len) -- cgit v1.1 From da335baf9e788edfb00ee3b96f7b9526b6b2f8a9 Mon Sep 17 00:00:00 2001 From: Gerrit Renker Date: Mon, 27 Nov 2006 12:26:57 -0200 Subject: [DCCP] ccid3: Avoid congestion control on zero-sized data packets This resolves an `XXX' in ccid3_hc_tx_send_packet(). The function is only called on Data and DataAck packets and returns a negative result on zero-sized messages. This is a reasonable policy since CCID 3 is a congestion-control module and congestion control on zero-sized Data(Ack) packets is in a way pathological. The patch uses a more suitable error code for this case, it returns the Posix.1 code `EBADMSG' ("Not a data message") instead of `ENOTCONN'. As a result of ignoring zero-sized packets, a the condition for a warning "First packet is data" in ccid3_hc_tx_packet_sent is always satisfied; this message has been removed since it will always be printed. Signed-off-by: Gerrit Renker Signed-off-by: Ian McDonald Signed-off-by: Arnaldo Carvalho de Melo --- net/dccp/ccids/ccid3.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) (limited to 'net/dccp/ccids') diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c index 2745d83..62c3042 100644 --- a/net/dccp/ccids/ccid3.c +++ b/net/dccp/ccids/ccid3.c @@ -264,13 +264,13 @@ static int ccid3_hc_tx_send_packet(struct sock *sk, BUG_ON(hctx == NULL); - /* Check if pure ACK or Terminating*/ /* - * XXX: We only call this function for DATA and DATAACK, on, these - * packets can have zero length, but why the comment about "pure ACK"? + * This function is called only for Data and DataAck packets. Sending + * zero-sized Data(Ack)s is theoretically possible, but for congestion + * control this case is pathological - ignore it. */ if (unlikely(len == 0)) - return -ENOTCONN; + return -EBADMSG; /* See if last packet allocated was not sent */ new_packet = dccp_tx_hist_head(&hctx->ccid3hctx_hist); @@ -387,11 +387,7 @@ static void ccid3_hc_tx_packet_sent(struct sock *sk, int more, int len) switch (hctx->ccid3hctx_state) { case TFRC_SSTATE_NO_SENT: - /* if first wasn't pure ack */ - if (len != 0) - DCCP_CRIT("%s, First packet sent is noted " - "as a data packet", dccp_role(sk)); - return; + /* fall through */ case TFRC_SSTATE_NO_FBACK: /* t_nom, t_ipi, delta do not change until feedback arrives */ return; -- cgit v1.1 From 70dbd5b0ef3915f1e018e6437c8db9e999b0d701 Mon Sep 17 00:00:00 2001 From: Gerrit Renker Date: Mon, 27 Nov 2006 12:27:55 -0200 Subject: [DCCP] ccid3: Remove redundant statements in ccid3_hc_tx_packet_sent This patch removes a switch statement which is redundant since, * nothing is done in states TFRC_SSTATE_NO_SENT/TFRC_SSTATE_NO_FBACK * it is impossible that the function is called in the state TFRC_SSTATE_TERM, since --the function is called, in dccp_write_xmit, after ccid3_hc_tx_send_packet --if ccid3_hc_tx_send_packet is called in state TFRC_SSTATE_TERM, it returns -EINVAL, which means that ccid3_hc_tx_packet_sent will not be called (compare dccp_write_xmit) --> therefore, this case is logically impossible * the remaining state is TFRC_SSTATE_FBACK which conditionally updates t_ipi, t_nom, and t_delta. This is a no-op, since --t_ipi only changes when feedback is received --however, when feedback arrives via ccid3_hc_tx_packet_recv, there is an identical code block which performs the same set of operations --performing the same set of operations again in ccid3_hc_tx_packet_sent therefore does not change anything, since between the time of receiving the last feedback (and therefore update of t_ipi, t_nom, and t_delta), the value of t_ipi has not changed --since t_ipi has not changed, the values of t_delta and t_nom also do not change, they depend fully on t_ipi Signed-off-by: Gerrit Renker Acked-by: Ian McDonald Signed-off-by: Arnaldo Carvalho de Melo --- net/dccp/ccids/ccid3.c | 21 --------------------- 1 file changed, 21 deletions(-) (limited to 'net/dccp/ccids') diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c index 62c3042..58f7cac 100644 --- a/net/dccp/ccids/ccid3.c +++ b/net/dccp/ccids/ccid3.c @@ -384,27 +384,6 @@ static void ccid3_hc_tx_packet_sent(struct sock *sk, int more, int len) } else ccid3_pr_debug("%s, sk=%p, seqno=%llu NOT inserted!\n", dccp_role(sk), sk, dp->dccps_gss); - - switch (hctx->ccid3hctx_state) { - case TFRC_SSTATE_NO_SENT: - /* fall through */ - case TFRC_SSTATE_NO_FBACK: - /* t_nom, t_ipi, delta do not change until feedback arrives */ - return; - case TFRC_SSTATE_FBACK: - if (len > 0) { - 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, - hctx->ccid3hctx_t_ipi); - } - break; - case TFRC_SSTATE_TERM: - DCCP_BUG("Illegal %s state TERM, sk=%p", dccp_role(sk), sk); - break; - } } static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) -- cgit v1.1 From 5e19e3fcd7351de1ca87c4797cca27ba55c7e55e Mon Sep 17 00:00:00 2001 From: Gerrit Renker Date: Mon, 27 Nov 2006 12:28:48 -0200 Subject: [DCCP] ccid3: Resolve small FIXME This considers the case - ACK received while no packet has been sent so far. Resolved by printing a (rate-limited) warning message. Further removes an unnecessary BUG_ON in ccid3_hc_tx_packet_recv, received feedback on a terminating connection is simply ignored. Signed-off-by: Gerrit Renker Signed-off-by: Ian McDonald Signed-off-by: Arnaldo Carvalho de Melo --- net/dccp/ccids/ccid3.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'net/dccp/ccids') diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c index 58f7cac..6777a7f 100644 --- a/net/dccp/ccids/ccid3.c +++ b/net/dccp/ccids/ccid3.c @@ -413,9 +413,6 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) pinv = opt_recv->ccid3or_loss_event_rate; switch (hctx->ccid3hctx_state) { - case TFRC_SSTATE_NO_SENT: - /* FIXME: what to do here? */ - return; case TFRC_SSTATE_NO_FBACK: case TFRC_SSTATE_FBACK: /* Calculate new round trip sample by @@ -521,8 +518,10 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) /* set idle flag */ hctx->ccid3hctx_idle = 1; break; - case TFRC_SSTATE_TERM: - DCCP_BUG("Illegal %s state TERM, sk=%p", dccp_role(sk), sk); + case TFRC_SSTATE_NO_SENT: + DCCP_WARN("Illegal ACK received - no packet has been sent\n"); + /* fall through */ + case TFRC_SSTATE_TERM: /* ignore feedback when closing */ break; } } -- cgit v1.1 From 48e03eee715b9e19df03153f2bcce6413632afcb Mon Sep 17 00:00:00 2001 From: Gerrit Renker Date: Mon, 27 Nov 2006 20:29:27 -0200 Subject: [DCCP] ccid3: Consolidate timer resets This patch concerns updating the value of the nofeedback timer when no feedback has been received so far. Since in this case the value of R is still undefined according to [RFC 3448, 4.2], we can not perform step (3) of [RFC 3448, 4.3]. A clarification is provided in [RFC 4342, sec. 5], which states that in these cases the nofeedback timer (still) expires "after two seconds". Many thanks to Ian McDonald for pointing this out and providing the clarification. The patch * implements [RFC 4342, sec. 5] with regard to the above case * consolidates handling timer restart by - adding an appropriate jump label and - initialising the timeout value Acked-by: Ian McDonald Signed-off-by: Gerrit Renker Signed-off-by: Arnaldo Carvalho de Melo --- net/dccp/ccids/ccid3.c | 18 +++++++++--------- net/dccp/ccids/ccid3.h | 2 +- 2 files changed, 10 insertions(+), 10 deletions(-) (limited to 'net/dccp/ccids') diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c index 6777a7f..9297fca 100644 --- a/net/dccp/ccids/ccid3.c +++ b/net/dccp/ccids/ccid3.c @@ -154,16 +154,14 @@ static void ccid3_hc_tx_update_x(struct sock *sk) static void ccid3_hc_tx_no_feedback_timer(unsigned long data) { struct sock *sk = (struct sock *)data; - unsigned long next_tmout = 0; struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk); + unsigned long next_tmout = USEC_PER_SEC / 5; bh_lock_sock(sk); if (sock_owned_by_user(sk)) { /* Try again later. */ /* XXX: set some sensible MIB */ - sk_reset_timer(sk, &hctx->ccid3hctx_no_feedback_timer, - jiffies + HZ / 5); - goto out; + goto restart_timer; } ccid3_pr_debug("%s, sk=%p, state=%s\n", dccp_role(sk), sk, @@ -183,9 +181,9 @@ static void ccid3_hc_tx_no_feedback_timer(unsigned long data) dccp_role(sk), sk, ccid3_tx_state_name(hctx->ccid3hctx_state), hctx->ccid3hctx_x); - next_tmout = max_t(u32, 2 * usecs_div(hctx->ccid3hctx_s, - hctx->ccid3hctx_x), - TFRC_INITIAL_TIMEOUT); + /* The value of R is still undefined and so we can not recompute + * the timout value. Keep initial value as per [RFC 4342, 5]. */ + next_tmout = TFRC_INITIAL_TIMEOUT; /* * FIXME - not sure above calculation is correct. See section * 5 of CCID3 11 should adjust tx_t_ipi and double that to @@ -239,9 +237,11 @@ static void ccid3_hc_tx_no_feedback_timer(unsigned long data) goto out; } - sk_reset_timer(sk, &hctx->ccid3hctx_no_feedback_timer, - jiffies + max_t(u32, 1, usecs_to_jiffies(next_tmout))); hctx->ccid3hctx_idle = 1; + +restart_timer: + sk_reset_timer(sk, &hctx->ccid3hctx_no_feedback_timer, + jiffies + usecs_to_jiffies(next_tmout)); out: bh_unlock_sock(sk); sock_put(sk); diff --git a/net/dccp/ccids/ccid3.h b/net/dccp/ccids/ccid3.h index 4621652..9709217 100644 --- a/net/dccp/ccids/ccid3.h +++ b/net/dccp/ccids/ccid3.h @@ -46,7 +46,7 @@ #define TFRC_STD_PACKET_SIZE 256 #define TFRC_MAX_PACKET_SIZE 65535 -/* Two seconds as per CCID3 spec */ +/* Two seconds as per RFC 3448 4.2 */ #define TFRC_INITIAL_TIMEOUT (2 * USEC_PER_SEC) /* In usecs - half the scheduling granularity as per RFC3448 4.6 */ -- cgit v1.1 From 17893bc1a632e195574dc0dd9751243f0d5993d2 Mon Sep 17 00:00:00 2001 From: Gerrit Renker Date: Mon, 27 Nov 2006 20:31:33 -0200 Subject: [DCCP] ccid3: Consistently update t_nom, t_ipi, t_delta This patch: * consolidates updating of parameters (t_nom, t_ipi, t_delta) which need to be updated at the same time, since they are inter-dependent * removes two inline functions which are no longer needed as a result of the above consolidation * resolves a FIXME regarding the re-calculation of t_ipi within the nofeedback timer, in the state where no feedback has previously been received * ties updating these parameters to updating the sending rate X, exploiting that all three parameters in turn depend on X; and using a small optimisation which can reduce the number of required instructions: only update the three parameters when X really changes Signed-off-by: Gerrit Renker Acked-by: Ian McDonald Signed-off-by: Arnaldo Carvalho de Melo --- net/dccp/ccids/ccid3.c | 38 +++++++++++++++++--------------------- 1 file changed, 17 insertions(+), 21 deletions(-) (limited to 'net/dccp/ccids') diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c index 9297fca..4342caf 100644 --- a/net/dccp/ccids/ccid3.c +++ b/net/dccp/ccids/ccid3.c @@ -100,19 +100,24 @@ static void ccid3_hc_tx_set_state(struct sock *sk, hctx->ccid3hctx_state = state; } -/* Calculate new t_ipi (inter packet interval) by t_ipi = s / X_inst */ -static inline void ccid3_calc_new_t_ipi(struct ccid3_hc_tx_sock *hctx) +/* + * Recalculate scheduled nominal send time t_nom, inter-packet interval + * t_ipi, and delta value. Should be called after each change to X. + */ +static inline void ccid3_update_send_time(struct ccid3_hc_tx_sock *hctx) { + timeval_sub_usecs(&hctx->ccid3hctx_t_nom, hctx->ccid3hctx_t_ipi); + + /* Calculate new t_ipi (inter packet interval) by t_ipi = s / X_inst */ hctx->ccid3hctx_t_ipi = usecs_div(hctx->ccid3hctx_s, hctx->ccid3hctx_x); -} -/* Calculate new delta by delta = min(t_ipi / 2, t_gran / 2) */ -static inline void ccid3_calc_new_delta(struct ccid3_hc_tx_sock *hctx) -{ + /* Update nominal send time with regard to the new t_ipi */ + timeval_add_usecs(&hctx->ccid3hctx_t_nom, hctx->ccid3hctx_t_ipi); + + /* Calculate new delta by delta = min(t_ipi / 2, t_gran / 2) */ hctx->ccid3hctx_delta = min_t(u32, hctx->ccid3hctx_t_ipi / 2, TFRC_OPSYS_HALF_TIME_GRAN); } - /* * Update X by * If (p > 0) @@ -126,6 +131,7 @@ static inline void ccid3_calc_new_delta(struct ccid3_hc_tx_sock *hctx) static void ccid3_hc_tx_update_x(struct sock *sk) { struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk); + const __u32 old_x = hctx->ccid3hctx_x; /* To avoid large error in calcX */ if (hctx->ccid3hctx_p >= TFRC_SMALLEST_P) { @@ -149,6 +155,8 @@ static void ccid3_hc_tx_update_x(struct sock *sk) hctx->ccid3hctx_t_ld = now; } } + if (hctx->ccid3hctx_x != old_x) + ccid3_update_send_time(hctx); } static void ccid3_hc_tx_no_feedback_timer(unsigned long data) @@ -184,11 +192,7 @@ static void ccid3_hc_tx_no_feedback_timer(unsigned long data) /* The value of R is still undefined and so we can not recompute * the timout value. Keep initial value as per [RFC 4342, 5]. */ next_tmout = TFRC_INITIAL_TIMEOUT; - /* - * FIXME - not sure above calculation is correct. See section - * 5 of CCID3 11 should adjust tx_t_ipi and double that to - * achieve it really - */ + ccid3_update_send_time(hctx); break; case TFRC_SSTATE_FBACK: /* @@ -479,17 +483,9 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) /* unschedule no feedback timer */ sk_stop_timer(sk, &hctx->ccid3hctx_no_feedback_timer); - /* Update sending rate */ + /* Update sending rate (and likely t_ipi, t_nom, and delta) */ ccid3_hc_tx_update_x(sk); - /* Update next send time */ - timeval_sub_usecs(&hctx->ccid3hctx_t_nom, - hctx->ccid3hctx_t_ipi); - ccid3_calc_new_t_ipi(hctx); - timeval_add_usecs(&hctx->ccid3hctx_t_nom, - hctx->ccid3hctx_t_ipi); - ccid3_calc_new_delta(hctx); - /* remove all packets older than the one acked from history */ dccp_tx_hist_purge_older(ccid3_tx_hist, &hctx->ccid3hctx_hist, packet); -- cgit v1.1 From 5d0dbc4a9b2d325458dcbf9a8329bd1d2cc7bd7e Mon Sep 17 00:00:00 2001 From: Gerrit Renker Date: Mon, 27 Nov 2006 20:32:37 -0200 Subject: [DCCP] ccid3: Consolidate handling of t_RTO This patch * removes setting t_RTO in ccid3_hc_tx_init (per [RFC 3448, 4.2], t_RTO is undefined until feedback has been received); * makes some trivial changes (updates of comments); * performs a small optimisation by exploiting that the feedback timeout uses the value of t_ipi. The way it is done is safe, because the timeouts appear after the changes to t_ipi, ensuring that up-to-date values are used; * in ccid3_hc_tx_packet_recv, moves the t_rto statement closer to the calculation of the next_tmout. This makes the code clearer to read and is also safe, since t_rto is not updated until the next call of ccid3_hc_tx_packet_recv, and is not read by the functions called via ccid_wait_for_ccid(); * removes a `max' statement in sk_reset_timer, this is not needed since the timeout value is always greater than 1E6 microseconds. * adds `XXX'es to highlight that currently the nofeedback timer is set in a non-standard way Signed-off-by: Gerrit Renker Acked-by: Ian McDonald Signed-off-by: Arnaldo Carvalho de Melo --- net/dccp/ccids/ccid3.c | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) (limited to 'net/dccp/ccids') diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c index 4342caf..f0ed67c 100644 --- a/net/dccp/ccids/ccid3.c +++ b/net/dccp/ccids/ccid3.c @@ -228,11 +228,10 @@ static void ccid3_hc_tx_no_feedback_timer(unsigned long data) } /* * Schedule no feedback timer to expire in - * max(4 * R, 2 * s / X) + * max(4 * t_RTO, 2 * s/X) = max(4 * t_RTO, 2 * t_ipi) + * XXX This is non-standard, RFC 3448, 4.3 uses 4 * R */ - next_tmout = max_t(u32, hctx->ccid3hctx_t_rto, - 2 * usecs_div(hctx->ccid3hctx_s, - hctx->ccid3hctx_x)); + next_tmout = max(hctx->ccid3hctx_t_rto, 2*hctx->ccid3hctx_t_ipi); break; case TFRC_SSTATE_NO_SENT: DCCP_BUG("Illegal %s state NO_SENT, sk=%p", dccp_role(sk), sk); @@ -460,10 +459,6 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) "r_sample=%us\n", dccp_role(sk), sk, hctx->ccid3hctx_rtt, r_sample); - /* Update timeout interval */ - 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 sec */ @@ -491,17 +486,22 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) &hctx->ccid3hctx_hist, packet); /* * As we have calculated new ipi, delta, t_nom it is possible that - * we now can send a packet, so wake up dccp_wait_for_ccids. + * we now can send a packet, so wake up dccp_wait_for_ccid */ sk->sk_write_space(sk); + + /* Update timeout interval. We use the alternative variant of + * [RFC 3448, 3.1] which sets the upper bound of t_rto to one + * second, as it is suggested for TCP (see RFC 2988, 2.4). */ + hctx->ccid3hctx_t_rto = max_t(u32, 4 * hctx->ccid3hctx_rtt, + USEC_PER_SEC ); /* * Schedule no feedback timer to expire in - * max(4 * R, 2 * s / X) + * max(4 * t_RTO, 2 * s/X) = max(4 * t_RTO, 2 * t_ipi) + * XXX This is non-standard, RFC 3448, 4.3 uses 4 * R */ - next_tmout = max(hctx->ccid3hctx_t_rto, - 2 * usecs_div(hctx->ccid3hctx_s, - hctx->ccid3hctx_x)); + next_tmout = max(hctx->ccid3hctx_t_rto, 2*hctx->ccid3hctx_t_ipi); ccid3_pr_debug("%s, sk=%p, Scheduled no feedback timer to " "expire in %lu jiffies (%luus)\n", @@ -509,7 +509,7 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) usecs_to_jiffies(next_tmout), next_tmout); sk_reset_timer(sk, &hctx->ccid3hctx_no_feedback_timer, - jiffies + max_t(u32, 1, usecs_to_jiffies(next_tmout))); + jiffies + usecs_to_jiffies(next_tmout)); /* set idle flag */ hctx->ccid3hctx_idle = 1; @@ -607,7 +607,6 @@ static int ccid3_hc_tx_init(struct ccid *ccid, struct sock *sk) /* Set transmission rate to 1 packet per second */ hctx->ccid3hctx_x = hctx->ccid3hctx_s; - hctx->ccid3hctx_t_rto = USEC_PER_SEC; hctx->ccid3hctx_state = TFRC_SSTATE_NO_SENT; INIT_LIST_HEAD(&hctx->ccid3hctx_hist); -- cgit v1.1 From 2a1fda6f6c01d7ac195c040f14edcf9f64a5451e Mon Sep 17 00:00:00 2001 From: Gerrit Renker Date: Tue, 28 Nov 2006 18:34:34 -0200 Subject: [DCCP] ccid3: Set NoFeedback Timeout according to RFC 3448 This corrects the setting of the nofeedback timer with regard to RFC 3448 - previously it was not set to max(4*R, 2*s/X) as specified. Using the maximum of 1 second as upper bound (as it was done before) can have detrimental effects, especially if R is small. Signed-off-by: Ian McDonald Signed-off-by: Gerrit Renker Signed-off-by: Arnaldo Carvalho de Melo --- net/dccp/ccids/ccid3.c | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) (limited to 'net/dccp/ccids') diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c index f0ed67c..577fd0e 100644 --- a/net/dccp/ccids/ccid3.c +++ b/net/dccp/ccids/ccid3.c @@ -163,7 +163,7 @@ 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); - unsigned long next_tmout = USEC_PER_SEC / 5; + unsigned long t_nfb = USEC_PER_SEC / 5; bh_lock_sock(sk); if (sock_owned_by_user(sk)) { @@ -191,7 +191,7 @@ static void ccid3_hc_tx_no_feedback_timer(unsigned long data) hctx->ccid3hctx_x); /* The value of R is still undefined and so we can not recompute * the timout value. Keep initial value as per [RFC 4342, 5]. */ - next_tmout = TFRC_INITIAL_TIMEOUT; + t_nfb = TFRC_INITIAL_TIMEOUT; ccid3_update_send_time(hctx); break; case TFRC_SSTATE_FBACK: @@ -228,10 +228,9 @@ static void ccid3_hc_tx_no_feedback_timer(unsigned long data) } /* * Schedule no feedback timer to expire in - * max(4 * t_RTO, 2 * s/X) = max(4 * t_RTO, 2 * t_ipi) - * XXX This is non-standard, RFC 3448, 4.3 uses 4 * R + * max(4 * R, 2 * s/X) = max(4 * R, 2 * t_ipi) */ - next_tmout = max(hctx->ccid3hctx_t_rto, 2*hctx->ccid3hctx_t_ipi); + t_nfb = max(4 * hctx->ccid3hctx_rtt, 2 * hctx->ccid3hctx_t_ipi); break; case TFRC_SSTATE_NO_SENT: DCCP_BUG("Illegal %s state NO_SENT, sk=%p", dccp_role(sk), sk); @@ -244,7 +243,7 @@ static void ccid3_hc_tx_no_feedback_timer(unsigned long data) restart_timer: sk_reset_timer(sk, &hctx->ccid3hctx_no_feedback_timer, - jiffies + usecs_to_jiffies(next_tmout)); + jiffies + usecs_to_jiffies(t_nfb)); out: bh_unlock_sock(sk); sock_put(sk); @@ -396,7 +395,7 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) struct ccid3_options_received *opt_recv; struct dccp_tx_hist_entry *packet; struct timeval now; - unsigned long next_tmout; + unsigned long t_nfb; u32 t_elapsed; u32 pinv; u32 x_recv; @@ -498,18 +497,17 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) USEC_PER_SEC ); /* * Schedule no feedback timer to expire in - * max(4 * t_RTO, 2 * s/X) = max(4 * t_RTO, 2 * t_ipi) - * XXX This is non-standard, RFC 3448, 4.3 uses 4 * R + * max(4 * R, 2 * s/X) = max(4 * R, 2 * t_ipi) */ - next_tmout = max(hctx->ccid3hctx_t_rto, 2*hctx->ccid3hctx_t_ipi); + t_nfb = max(4 * hctx->ccid3hctx_rtt, 2 * hctx->ccid3hctx_t_ipi); ccid3_pr_debug("%s, sk=%p, Scheduled no feedback timer to " "expire in %lu jiffies (%luus)\n", dccp_role(sk), sk, - usecs_to_jiffies(next_tmout), next_tmout); + usecs_to_jiffies(t_nfb), t_nfb); sk_reset_timer(sk, &hctx->ccid3hctx_no_feedback_timer, - jiffies + usecs_to_jiffies(next_tmout)); + jiffies + usecs_to_jiffies(t_nfb)); /* set idle flag */ hctx->ccid3hctx_idle = 1; -- cgit v1.1 From 78ad713da673a2977763521c347176137f3e493f Mon Sep 17 00:00:00 2001 From: Gerrit Renker Date: Tue, 28 Nov 2006 19:22:33 -0200 Subject: [DCCP] ccid3: Track RX/TX packet size `s' using moving-average Problem: --- net/dccp/ccids/ccid3.c | 60 ++++++++++++++++++++++++++++++++++---------------- 1 file changed, 41 insertions(+), 19 deletions(-) (limited to 'net/dccp/ccids') diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c index 577fd0e..05513f3 100644 --- a/net/dccp/ccids/ccid3.c +++ b/net/dccp/ccids/ccid3.c @@ -159,6 +159,25 @@ static void ccid3_hc_tx_update_x(struct sock *sk) ccid3_update_send_time(hctx); } +/* + * Track the mean packet size `s' (cf. RFC 4342, 5.3 and RFC 3448, 4.1) + * @len: DCCP packet payload size in bytes + */ +static inline void ccid3_hc_tx_update_s(struct ccid3_hc_tx_sock *hctx, int len) +{ + if (unlikely(len == 0)) + ccid3_pr_debug("Packet payload length is 0 - not updating\n"); + else + hctx->ccid3hctx_s = hctx->ccid3hctx_s == 0 ? len : + (9 * hctx->ccid3hctx_s + len) / 10; + /* + * Note: We could do a potential optimisation here - when `s' changes, + * recalculate sending rate and consequently t_ipi, t_delta, and + * t_now. This is however non-standard, and the benefits are not + * clear, so it is currently left out. + */ +} + static void ccid3_hc_tx_no_feedback_timer(unsigned long data) { struct sock *sk = (struct sock *)data; @@ -299,6 +318,10 @@ static int ccid3_hc_tx_send_packet(struct sock *sk, hctx->ccid3hctx_t_last_win_count = now; ccid3_hc_tx_set_state(sk, TFRC_SSTATE_NO_FBACK); + /* Set initial sending rate to 1 packet per second */ + ccid3_hc_tx_update_s(hctx, len); + hctx->ccid3hctx_x = hctx->ccid3hctx_s; + /* First timeout, according to [RFC 3448, 4.2], is 1 second */ hctx->ccid3hctx_t_ipi = USEC_PER_SEC; /* Initial delta: minimum of 0.5 sec and t_gran/2 */ @@ -350,6 +373,8 @@ static void ccid3_hc_tx_packet_sent(struct sock *sk, int more, int len) unsigned long quarter_rtt; struct dccp_tx_hist_entry *packet; + ccid3_hc_tx_update_s(hctx, len); + packet = dccp_tx_hist_head(&hctx->ccid3hctx_hist); if (unlikely(packet == NULL)) { DCCP_WARN("packet doesn't exist in history!\n"); @@ -594,17 +619,9 @@ static int ccid3_hc_tx_parse_options(struct sock *sk, unsigned char option, static int ccid3_hc_tx_init(struct ccid *ccid, struct sock *sk) { - struct dccp_sock *dp = dccp_sk(sk); struct ccid3_hc_tx_sock *hctx = ccid_priv(ccid); - if (dp->dccps_packet_size >= TFRC_MIN_PACKET_SIZE && - dp->dccps_packet_size <= TFRC_MAX_PACKET_SIZE) - hctx->ccid3hctx_s = dp->dccps_packet_size; - else - hctx->ccid3hctx_s = TFRC_STD_PACKET_SIZE; - - /* Set transmission rate to 1 packet per second */ - hctx->ccid3hctx_x = hctx->ccid3hctx_s; + hctx->ccid3hctx_s = 0; hctx->ccid3hctx_state = TFRC_SSTATE_NO_SENT; INIT_LIST_HEAD(&hctx->ccid3hctx_hist); @@ -658,6 +675,15 @@ static void ccid3_hc_rx_set_state(struct sock *sk, hcrx->ccid3hcrx_state = state; } +static inline void ccid3_hc_rx_update_s(struct ccid3_hc_rx_sock *hcrx, int len) +{ + if (unlikely(len == 0)) /* don't update on empty packets (e.g. ACKs) */ + ccid3_pr_debug("Packet payload length is 0 - not updating\n"); + else + hcrx->ccid3hcrx_s = hcrx->ccid3hcrx_s == 0 ? len : + (9 * hcrx->ccid3hcrx_s + len) / 10; +} + static void ccid3_hc_rx_send_feedback(struct sock *sk) { struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk); @@ -934,7 +960,7 @@ static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb) struct dccp_rx_hist_entry *packet; struct timeval now; u32 p_prev, rtt_prev, r_sample, t_elapsed; - int loss; + int loss, payload_size; BUG_ON(hcrx == NULL); @@ -989,6 +1015,9 @@ static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb) if (DCCP_SKB_CB(skb)->dccpd_type == DCCP_PKT_ACK) return; + payload_size = skb->len - dccp_hdr(skb)->dccph_doff * 4; + ccid3_hc_rx_update_s(hcrx, payload_size); + switch (hcrx->ccid3hcrx_state) { case TFRC_RSTATE_NO_DATA: ccid3_pr_debug("%s, sk=%p(%s), skb=%p, sending initial " @@ -999,8 +1028,7 @@ static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb) ccid3_hc_rx_set_state(sk, TFRC_RSTATE_DATA); return; case TFRC_RSTATE_DATA: - hcrx->ccid3hcrx_bytes_recv += skb->len - - dccp_hdr(skb)->dccph_doff * 4; + hcrx->ccid3hcrx_bytes_recv += payload_size; if (loss) break; @@ -1040,22 +1068,16 @@ static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb) static int ccid3_hc_rx_init(struct ccid *ccid, struct sock *sk) { - struct dccp_sock *dp = dccp_sk(sk); struct ccid3_hc_rx_sock *hcrx = ccid_priv(ccid); ccid3_pr_debug("%s, sk=%p\n", dccp_role(sk), sk); - if (dp->dccps_packet_size >= TFRC_MIN_PACKET_SIZE && - dp->dccps_packet_size <= TFRC_MAX_PACKET_SIZE) - hcrx->ccid3hcrx_s = dp->dccps_packet_size; - else - hcrx->ccid3hcrx_s = TFRC_STD_PACKET_SIZE; - 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_s = 0; hcrx->ccid3hcrx_rtt = 5000; /* XXX 5ms for now... */ return 0; } -- cgit v1.1 From 5aed324369c94a2c38469c8288e42eb1a9fac400 Mon Sep 17 00:00:00 2001 From: Gerrit Renker Date: Tue, 28 Nov 2006 19:33:36 -0200 Subject: [DCCP]: Tidy up unused structures This removes and cleans up unused variables and structures which have become unnecessary following the introduction of the EWMA patch to automatically track the CCID 3 receiver/sender packet sizes `s'. It deprecates the PACKET_SIZE socket option by returning an error code and printing a deprecation warning if an application tries to read or write this socket option. Signed-off-by: Gerrit Renker Signed-off-by: Arnaldo Carvalho de Melo --- net/dccp/ccids/ccid3.h | 4 ---- 1 file changed, 4 deletions(-) (limited to 'net/dccp/ccids') diff --git a/net/dccp/ccids/ccid3.h b/net/dccp/ccids/ccid3.h index 9709217..dbb8844 100644 --- a/net/dccp/ccids/ccid3.h +++ b/net/dccp/ccids/ccid3.h @@ -42,10 +42,6 @@ #include #include "../ccid.h" -#define TFRC_MIN_PACKET_SIZE 16 -#define TFRC_STD_PACKET_SIZE 256 -#define TFRC_MAX_PACKET_SIZE 65535 - /* Two seconds as per RFC 3448 4.2 */ #define TFRC_INITIAL_TIMEOUT (2 * USEC_PER_SEC) -- cgit v1.1 From a79ef76f4d8424324c2f108824a7398571193f43 Mon Sep 17 00:00:00 2001 From: Gerrit Renker Date: Tue, 28 Nov 2006 19:51:42 -0200 Subject: [DCCP] ccid3: Larger initial windows This implements the larger-initial-windows feature for CCID 3, as described in section 5 of RFC 4342. When the first feedback packet arrives, the sender can send up to 2..4 packets per RTT, instead of just one. The patch further * reduces the number of timestamping calls by passing the timestamp value (which is computed in one of the calling functions anyway) as argument * renames one constant with a very long name into one which is shorter and resembles the one in RFC 3448 (t_mbi) * simplifies some of the min_t/max_t cases where both `x', `y' have the same type Commiter note: renamed TFRC_t_mbi to TFRC_T_MBI, to follow Linux coding style. Signed-off-by: Gerrit Renker Acked-by: Ian McDonald Signed-off-by: Arnaldo Carvalho de Melo --- net/dccp/ccids/ccid3.c | 66 ++++++++++++++++++++++++++------------------------ net/dccp/ccids/ccid3.h | 4 +-- 2 files changed, 37 insertions(+), 33 deletions(-) (limited to 'net/dccp/ccids') diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c index 05513f3..aa5440e 100644 --- a/net/dccp/ccids/ccid3.c +++ b/net/dccp/ccids/ccid3.c @@ -128,7 +128,8 @@ static inline void ccid3_update_send_time(struct ccid3_hc_tx_sock *hctx) * X = max(min(2 * X, 2 * X_recv), s / R); * tld = now; */ -static void ccid3_hc_tx_update_x(struct sock *sk) +static void ccid3_hc_tx_update_x(struct sock *sk, struct timeval *now) + { struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk); const __u32 old_x = hctx->ccid3hctx_x; @@ -138,23 +139,20 @@ static void ccid3_hc_tx_update_x(struct sock *sk) hctx->ccid3hctx_x_calc = tfrc_calc_x(hctx->ccid3hctx_s, hctx->ccid3hctx_rtt, hctx->ccid3hctx_p); - hctx->ccid3hctx_x = max_t(u32, min_t(u32, hctx->ccid3hctx_x_calc, - 2 * hctx->ccid3hctx_x_recv), - (hctx->ccid3hctx_s / - TFRC_MAX_BACK_OFF_TIME)); - } else { - struct timeval now; + hctx->ccid3hctx_x = max_t(u32, min(hctx->ccid3hctx_x_calc, + hctx->ccid3hctx_x_recv * 2), + hctx->ccid3hctx_s / TFRC_T_MBI); + + } else if (timeval_delta(now, &hctx->ccid3hctx_t_ld) >= + hctx->ccid3hctx_rtt) { + hctx->ccid3hctx_x = max(min(hctx->ccid3hctx_x_recv, + hctx->ccid3hctx_x ) * 2, + usecs_div(hctx->ccid3hctx_s, + hctx->ccid3hctx_rtt) ); + hctx->ccid3hctx_t_ld = *now; + } else + ccid3_pr_debug("Not changing X\n"); - dccp_timestamp(sk, &now); - if (timeval_delta(&now, &hctx->ccid3hctx_t_ld) >= - hctx->ccid3hctx_rtt) { - hctx->ccid3hctx_x = max_t(u32, min_t(u32, hctx->ccid3hctx_x_recv, - hctx->ccid3hctx_x) * 2, - usecs_div(hctx->ccid3hctx_s, - hctx->ccid3hctx_rtt)); - hctx->ccid3hctx_t_ld = now; - } - } if (hctx->ccid3hctx_x != old_x) ccid3_update_send_time(hctx); } @@ -196,12 +194,9 @@ static void ccid3_hc_tx_no_feedback_timer(unsigned long data) switch (hctx->ccid3hctx_state) { case TFRC_SSTATE_NO_FBACK: - /* Halve send rate */ - hctx->ccid3hctx_x /= 2; - if (hctx->ccid3hctx_x < (hctx->ccid3hctx_s / - TFRC_MAX_BACK_OFF_TIME)) - hctx->ccid3hctx_x = (hctx->ccid3hctx_s / - TFRC_MAX_BACK_OFF_TIME); + /* RFC 3448, 4.4: Halve send rate directly */ + hctx->ccid3hctx_x = min_t(u32, hctx->ccid3hctx_x / 2, + hctx->ccid3hctx_s / TFRC_T_MBI); ccid3_pr_debug("%s, sk=%p, state=%s, updated tx rate to %d " "bytes/s\n", @@ -221,6 +216,8 @@ static void ccid3_hc_tx_no_feedback_timer(unsigned long data) if (!hctx->ccid3hctx_idle || (hctx->ccid3hctx_x_recv >= 4 * usecs_div(hctx->ccid3hctx_s, hctx->ccid3hctx_rtt))) { + struct timeval now; + ccid3_pr_debug("%s, sk=%p, state=%s, not idle\n", dccp_role(sk), sk, ccid3_tx_state_name(hctx->ccid3hctx_state)); @@ -238,12 +235,13 @@ static void ccid3_hc_tx_no_feedback_timer(unsigned long data) if (hctx->ccid3hctx_p < TFRC_SMALLEST_P || hctx->ccid3hctx_x_calc > 2 * hctx->ccid3hctx_x_recv) hctx->ccid3hctx_x_recv = max_t(u32, hctx->ccid3hctx_x_recv / 2, - hctx->ccid3hctx_s / (2 * TFRC_MAX_BACK_OFF_TIME)); + hctx->ccid3hctx_s / (2 * TFRC_T_MBI)); else hctx->ccid3hctx_x_recv = hctx->ccid3hctx_x_calc / 4; /* Update sending rate */ - ccid3_hc_tx_update_x(sk); + dccp_timestamp(sk, &now); + ccid3_hc_tx_update_x(sk, &now); } /* * Schedule no feedback timer to expire in @@ -473,11 +471,21 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) * q is a constant, RFC 3448 recomments 0.9 */ if (hctx->ccid3hctx_state == TFRC_SSTATE_NO_FBACK) { + /* Use Larger Initial Windows [RFC 4342, sec. 5] + * We deviate in that we use `s' instead of `MSS'. */ + u16 w_init = max( 4 * hctx->ccid3hctx_s, + max(2 * hctx->ccid3hctx_s, 4380)); + hctx->ccid3hctx_rtt = r_sample; + hctx->ccid3hctx_x = usecs_div(w_init, r_sample); + hctx->ccid3hctx_t_ld = now; + + ccid3_update_send_time(hctx); ccid3_hc_tx_set_state(sk, TFRC_SSTATE_FBACK); - hctx->ccid3hctx_rtt = r_sample; - } else + } else { hctx->ccid3hctx_rtt = (hctx->ccid3hctx_rtt * 9) / 10 + r_sample / 10; + ccid3_hc_tx_update_x(sk, &now); + } ccid3_pr_debug("%s, sk=%p, New RTT estimate=%uus, " "r_sample=%us\n", dccp_role(sk), sk, @@ -502,9 +510,6 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) /* unschedule no feedback timer */ sk_stop_timer(sk, &hctx->ccid3hctx_no_feedback_timer); - /* Update sending rate (and likely t_ipi, t_nom, and delta) */ - ccid3_hc_tx_update_x(sk); - /* remove all packets older than the one acked from history */ dccp_tx_hist_purge_older(ccid3_tx_hist, &hctx->ccid3hctx_hist, packet); @@ -514,7 +519,6 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) */ sk->sk_write_space(sk); - /* Update timeout interval. We use the alternative variant of * [RFC 3448, 3.1] which sets the upper bound of t_rto to one * second, as it is suggested for TCP (see RFC 2988, 2.4). */ diff --git a/net/dccp/ccids/ccid3.h b/net/dccp/ccids/ccid3.h index dbb8844..27cb20a 100644 --- a/net/dccp/ccids/ccid3.h +++ b/net/dccp/ccids/ccid3.h @@ -48,8 +48,8 @@ /* In usecs - half the scheduling granularity as per RFC3448 4.6 */ #define TFRC_OPSYS_HALF_TIME_GRAN (USEC_PER_SEC / (2 * HZ)) -/* In seconds */ -#define TFRC_MAX_BACK_OFF_TIME 64 +/* Parameter t_mbi from [RFC 3448, 4.3]: backoff interval in seconds */ +#define TFRC_T_MBI 64 #define TFRC_SMALLEST_P 40 -- cgit v1.1 From 6b57c93dc3aa0115b589cb89ef862d46ab9bd95e Mon Sep 17 00:00:00 2001 From: Gerrit Renker Date: Tue, 28 Nov 2006 19:55:06 -0200 Subject: [DCCP]: Use `unsigned' for packet lengths This patch implements a suggestion by Ian McDonald and 1) Avoids tests against negative packet lengths by using unsigned int for packet payload lengths in the CCID send_packet()/packet_sent() routines 2) As a consequence, it removes an now unnecessary test with regard to `len > 0' in ccid3_hc_tx_packet_sent: that condition is always true, since * negative packet lengths are avoided * ccid3_hc_tx_send_packet flags an error whenever the payload length is 0. As a consequence, ccid3_hc_tx_packet_sent is never called as all errors returned by ccid_hc_tx_send_packet are caught in dccp_write_xmit 3) Removes the third argument of ccid_hc_tx_send_packet (the `len' parameter), since it is currently always set to skb->len. The code is updated with regard to this parameter change. Signed-off-by: Gerrit Renker Signed-off-by: Ian McDonald Signed-off-by: Arnaldo Carvalho de Melo --- net/dccp/ccids/ccid2.c | 5 ++- net/dccp/ccids/ccid3.c | 83 +++++++++++++++++++++++--------------------------- 2 files changed, 40 insertions(+), 48 deletions(-) (limited to 'net/dccp/ccids') diff --git a/net/dccp/ccids/ccid2.c b/net/dccp/ccids/ccid2.c index 207f7f9..2555be8 100644 --- a/net/dccp/ccids/ccid2.c +++ b/net/dccp/ccids/ccid2.c @@ -125,8 +125,7 @@ static int ccid2_hc_tx_alloc_seq(struct ccid2_hc_tx_sock *hctx, int num, return 0; } -static int ccid2_hc_tx_send_packet(struct sock *sk, - struct sk_buff *skb, int len) +static int ccid2_hc_tx_send_packet(struct sock *sk, struct sk_buff *skb) { struct ccid2_hc_tx_sock *hctx; @@ -268,7 +267,7 @@ static void ccid2_start_rto_timer(struct sock *sk) jiffies + hctx->ccid2hctx_rto); } -static void ccid2_hc_tx_packet_sent(struct sock *sk, int more, int len) +static void ccid2_hc_tx_packet_sent(struct sock *sk, int more, unsigned int len) { struct dccp_sock *dp = dccp_sk(sk); struct ccid2_hc_tx_sock *hctx = ccid2_hc_tx_sk(sk); diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c index aa5440e..70ebe70 100644 --- a/net/dccp/ccids/ccid3.c +++ b/net/dccp/ccids/ccid3.c @@ -272,8 +272,7 @@ out: * = 0: can send immediately * < 0: error condition; do not send packet */ -static int ccid3_hc_tx_send_packet(struct sock *sk, - struct sk_buff *skb, int len) +static int ccid3_hc_tx_send_packet(struct sock *sk, struct sk_buff *skb) { struct dccp_sock *dp = dccp_sk(sk); struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk); @@ -288,7 +287,7 @@ static int ccid3_hc_tx_send_packet(struct sock *sk, * zero-sized Data(Ack)s is theoretically possible, but for congestion * control this case is pathological - ignore it. */ - if (unlikely(len == 0)) + if (unlikely(skb->len == 0)) return -EBADMSG; /* See if last packet allocated was not sent */ @@ -317,7 +316,7 @@ static int ccid3_hc_tx_send_packet(struct sock *sk, ccid3_hc_tx_set_state(sk, TFRC_SSTATE_NO_FBACK); /* Set initial sending rate to 1 packet per second */ - ccid3_hc_tx_update_s(hctx, len); + ccid3_hc_tx_update_s(hctx, skb->len); hctx->ccid3hctx_x = hctx->ccid3hctx_s; /* First timeout, according to [RFC 3448, 4.2], is 1 second */ @@ -356,59 +355,53 @@ static int ccid3_hc_tx_send_packet(struct sock *sk, return 0; } -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, unsigned int len) { const struct dccp_sock *dp = dccp_sk(sk); struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk); struct timeval now; + unsigned long quarter_rtt; + struct dccp_tx_hist_entry *packet; BUG_ON(hctx == NULL); dccp_timestamp(sk, &now); - /* check if we have sent a data packet */ - if (len > 0) { - unsigned long quarter_rtt; - struct dccp_tx_hist_entry *packet; + ccid3_hc_tx_update_s(hctx, len); - ccid3_hc_tx_update_s(hctx, len); + packet = dccp_tx_hist_head(&hctx->ccid3hctx_hist); + if (unlikely(packet == NULL)) { + DCCP_WARN("packet doesn't exist in history!\n"); + return; + } + if (unlikely(packet->dccphtx_sent)) { + DCCP_WARN("no unsent packet in history!\n"); + return; + } + packet->dccphtx_tstamp = now; + packet->dccphtx_seqno = dp->dccps_gss; + /* + * Check if win_count have changed + * Algorithm in "8.1. Window Counter Value" in RFC 4342. + */ + quarter_rtt = timeval_delta(&now, &hctx->ccid3hctx_t_last_win_count); + if (likely(hctx->ccid3hctx_rtt > 8)) + quarter_rtt /= hctx->ccid3hctx_rtt / 4; - packet = dccp_tx_hist_head(&hctx->ccid3hctx_hist); - if (unlikely(packet == NULL)) { - DCCP_WARN("packet doesn't exist in history!\n"); - return; - } - if (unlikely(packet->dccphtx_sent)) { - DCCP_WARN("no unsent packet in history!\n"); - return; - } - packet->dccphtx_tstamp = now; - packet->dccphtx_seqno = dp->dccps_gss; - /* - * Check if win_count have changed - * Algorithm in "8.1. Window Counter Value" in RFC 4342. - */ - quarter_rtt = timeval_delta(&now, &hctx->ccid3hctx_t_last_win_count); - if (likely(hctx->ccid3hctx_rtt > 8)) - quarter_rtt /= hctx->ccid3hctx_rtt / 4; - - if (quarter_rtt > 0) { - hctx->ccid3hctx_t_last_win_count = now; - hctx->ccid3hctx_last_win_count = (hctx->ccid3hctx_last_win_count + - min_t(unsigned long, quarter_rtt, 5)) % 16; - ccid3_pr_debug("%s, sk=%p, window changed from " - "%u to %u!\n", - dccp_role(sk), sk, - packet->dccphtx_ccval, - hctx->ccid3hctx_last_win_count); - } + if (quarter_rtt > 0) { + hctx->ccid3hctx_t_last_win_count = now; + hctx->ccid3hctx_last_win_count = (hctx->ccid3hctx_last_win_count + + min_t(unsigned long, quarter_rtt, 5)) % 16; + ccid3_pr_debug("%s, sk=%p, window changed from " + "%u to %u!\n", + dccp_role(sk), sk, + packet->dccphtx_ccval, + hctx->ccid3hctx_last_win_count); + } - hctx->ccid3hctx_idle = 0; - packet->dccphtx_rtt = hctx->ccid3hctx_rtt; - packet->dccphtx_sent = 1; - } else - ccid3_pr_debug("%s, sk=%p, seqno=%llu NOT inserted!\n", - dccp_role(sk), sk, dp->dccps_gss); + hctx->ccid3hctx_idle = 0; + packet->dccphtx_rtt = hctx->ccid3hctx_rtt; + packet->dccphtx_sent = 1; } static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) -- cgit v1.1