aboutsummaryrefslogtreecommitdiff
path: root/net/dccp
diff options
context:
space:
mode:
Diffstat (limited to 'net/dccp')
-rw-r--r--net/dccp/Kconfig11
-rw-r--r--net/dccp/Makefile8
-rw-r--r--net/dccp/ackvec.c128
-rw-r--r--net/dccp/ackvec.h23
-rw-r--r--net/dccp/ccid.h12
-rw-r--r--net/dccp/ccids/Kconfig42
-rw-r--r--net/dccp/ccids/ccid2.c65
-rw-r--r--net/dccp/ccids/ccid2.h3
-rw-r--r--net/dccp/ccids/ccid3.c550
-rw-r--r--net/dccp/ccids/ccid3.h119
-rw-r--r--net/dccp/ccids/lib/loss_interval.c6
-rw-r--r--net/dccp/ccids/lib/tfrc_equation.c7
-rw-r--r--net/dccp/dccp.h112
-rw-r--r--net/dccp/feat.c131
-rw-r--r--net/dccp/feat.h48
-rw-r--r--net/dccp/input.c67
-rw-r--r--net/dccp/ipv4.c539
-rw-r--r--net/dccp/ipv6.c625
-rw-r--r--net/dccp/minisocks.c48
-rw-r--r--net/dccp/options.c63
-rw-r--r--net/dccp/output.c84
-rw-r--r--net/dccp/probe.c8
-rw-r--r--net/dccp/proto.c64
-rw-r--r--net/dccp/sysctl.c60
-rw-r--r--net/dccp/timer.c134
25 files changed, 1520 insertions, 1437 deletions
diff --git a/net/dccp/Kconfig b/net/dccp/Kconfig
index e2a095d0fd8..b8a68dd4100 100644
--- a/net/dccp/Kconfig
+++ b/net/dccp/Kconfig
@@ -4,15 +4,15 @@ menu "DCCP Configuration (EXPERIMENTAL)"
config IP_DCCP
tristate "The DCCP Protocol (EXPERIMENTAL)"
---help---
- Datagram Congestion Control Protocol
+ Datagram Congestion Control Protocol (RFC 4340)
- From draft-ietf-dccp-spec-11 <http://www.icir.org/kohler/dcp/draft-ietf-dccp-spec-11.txt>.
+ From http://www.ietf.org/rfc/rfc4340.txt:
The Datagram Congestion Control Protocol (DCCP) is a transport
protocol that implements bidirectional, unicast connections of
congestion-controlled, unreliable datagrams. It should be suitable
for use by applications such as streaming media, Internet telephony,
- and on-line games
+ and on-line games.
To compile this protocol support as a module, choose M here: the
module will be called dccp.
@@ -38,6 +38,9 @@ config IP_DCCP_DEBUG
---help---
Only use this if you're hacking DCCP.
+ When compiling DCCP as a module, this debugging output can be toggled
+ by setting the parameter dccp_debug of the `dccp' module to 0 or 1.
+
Just say N.
config NET_DCCPPROBE
@@ -49,7 +52,7 @@ config NET_DCCPPROBE
DCCP congestion avoidance modules. If you don't understand
what was just said, you don't need it: say N.
- Documentation on how to use the packet generator can be found
+ Documentation on how to use DCCP connection probing can be found
at http://linux-net.osdl.org/index.php/DccpProbe
To compile this code as a module, choose M here: the
diff --git a/net/dccp/Makefile b/net/dccp/Makefile
index 17ed99c4661..f4f8793aaff 100644
--- a/net/dccp/Makefile
+++ b/net/dccp/Makefile
@@ -1,13 +1,13 @@
-obj-$(CONFIG_IPV6) += dccp_ipv6.o
-
-dccp_ipv6-y := ipv6.o
-
obj-$(CONFIG_IP_DCCP) += dccp.o dccp_ipv4.o
dccp-y := ccid.o feat.o input.o minisocks.o options.o output.o proto.o timer.o
dccp_ipv4-y := ipv4.o
+# build dccp_ipv6 as module whenever either IPv6 or DCCP is a module
+obj-$(subst y,$(CONFIG_IP_DCCP),$(CONFIG_IPV6)) += dccp_ipv6.o
+dccp_ipv6-y := ipv6.o
+
dccp-$(CONFIG_IP_DCCP_ACKVEC) += ackvec.o
obj-$(CONFIG_INET_DCCP_DIAG) += dccp_diag.o
diff --git a/net/dccp/ackvec.c b/net/dccp/ackvec.c
index 4d176d33983..bdf1bb7a82c 100644
--- a/net/dccp/ackvec.c
+++ b/net/dccp/ackvec.c
@@ -67,15 +67,16 @@ static void dccp_ackvec_insert_avr(struct dccp_ackvec *av,
int dccp_insert_option_ackvec(struct sock *sk, struct sk_buff *skb)
{
struct dccp_sock *dp = dccp_sk(sk);
-#ifdef CONFIG_IP_DCCP_DEBUG
- const char *debug_prefix = dp->dccps_role == DCCP_ROLE_CLIENT ?
- "CLIENT tx: " : "server tx: ";
-#endif
struct dccp_ackvec *av = dp->dccps_hc_rx_ackvec;
- int len = av->dccpav_vec_len + 2;
+ /* Figure out how many options do we need to represent the ackvec */
+ const u16 nr_opts = (av->dccpav_vec_len +
+ DCCP_MAX_ACKVEC_OPT_LEN - 1) /
+ DCCP_MAX_ACKVEC_OPT_LEN;
+ u16 len = av->dccpav_vec_len + 2 * nr_opts, i;
struct timeval now;
u32 elapsed_time;
- unsigned char *to, *from;
+ const unsigned char *tail, *from;
+ unsigned char *to;
struct dccp_ackvec_record *avr;
if (DCCP_SKB_CB(skb)->dccpd_opt_len + len > DCCP_MAX_OPT_LEN)
@@ -94,26 +95,39 @@ int dccp_insert_option_ackvec(struct sock *sk, struct sk_buff *skb)
DCCP_SKB_CB(skb)->dccpd_opt_len += len;
- to = skb_push(skb, len);
- *to++ = DCCPO_ACK_VECTOR_0;
- *to++ = len;
-
+ to = skb_push(skb, len);
len = av->dccpav_vec_len;
from = av->dccpav_buf + av->dccpav_buf_head;
+ tail = av->dccpav_buf + DCCP_MAX_ACKVEC_LEN;
+
+ for (i = 0; i < nr_opts; ++i) {
+ int copylen = len;
- /* Check if buf_head wraps */
- if ((int)av->dccpav_buf_head + len > DCCP_MAX_ACKVEC_LEN) {
- const u32 tailsize = DCCP_MAX_ACKVEC_LEN - av->dccpav_buf_head;
+ if (len > DCCP_MAX_ACKVEC_OPT_LEN)
+ copylen = DCCP_MAX_ACKVEC_OPT_LEN;
+
+ *to++ = DCCPO_ACK_VECTOR_0;
+ *to++ = copylen + 2;
+
+ /* Check if buf_head wraps */
+ if (from + copylen > tail) {
+ const u16 tailsize = tail - from;
+
+ memcpy(to, from, tailsize);
+ to += tailsize;
+ len -= tailsize;
+ copylen -= tailsize;
+ from = av->dccpav_buf;
+ }
- memcpy(to, from, tailsize);
- to += tailsize;
- len -= tailsize;
- from = av->dccpav_buf;
+ memcpy(to, from, copylen);
+ from += copylen;
+ to += copylen;
+ len -= copylen;
}
- memcpy(to, from, len);
/*
- * From draft-ietf-dccp-spec-11.txt:
+ * From RFC 4340, A.2:
*
* For each acknowledgement it sends, the HC-Receiver will add an
* acknowledgement record. ack_seqno will equal the HC-Receiver
@@ -129,9 +143,9 @@ int dccp_insert_option_ackvec(struct sock *sk, struct sk_buff *skb)
dccp_ackvec_insert_avr(av, avr);
- dccp_pr_debug("%sACK Vector 0, len=%d, ack_seqno=%llu, "
+ dccp_pr_debug("%s ACK Vector 0, len=%d, ack_seqno=%llu, "
"ack_ackno=%llu\n",
- debug_prefix, avr->dccpavr_sent_len,
+ dccp_role(sk), avr->dccpavr_sent_len,
(unsigned long long)avr->dccpavr_ack_seqno,
(unsigned long long)avr->dccpavr_ack_ackno);
return 0;
@@ -145,7 +159,6 @@ struct dccp_ackvec *dccp_ackvec_alloc(const gfp_t priority)
av->dccpav_buf_head = DCCP_MAX_ACKVEC_LEN - 1;
av->dccpav_buf_ackno = DCCP_MAX_SEQNO + 1;
av->dccpav_buf_nonce = av->dccpav_buf_nonce = 0;
- av->dccpav_ack_ptr = 0;
av->dccpav_time.tv_sec = 0;
av->dccpav_time.tv_usec = 0;
av->dccpav_vec_len = 0;
@@ -174,13 +187,13 @@ void dccp_ackvec_free(struct dccp_ackvec *av)
}
static inline u8 dccp_ackvec_state(const struct dccp_ackvec *av,
- const u8 index)
+ const u32 index)
{
return av->dccpav_buf[index] & DCCP_ACKVEC_STATE_MASK;
}
static inline u8 dccp_ackvec_len(const struct dccp_ackvec *av,
- const u8 index)
+ const u32 index)
{
return av->dccpav_buf[index] & DCCP_ACKVEC_LEN_MASK;
}
@@ -224,7 +237,7 @@ static inline int dccp_ackvec_set_buf_head_state(struct dccp_ackvec *av,
}
/*
- * Implements the draft-ietf-dccp-spec-11.txt Appendix A
+ * Implements the RFC 4340, Appendix A
*/
int dccp_ackvec_add(struct dccp_ackvec *av, const struct sock *sk,
const u64 ackno, const u8 state)
@@ -237,7 +250,7 @@ int dccp_ackvec_add(struct dccp_ackvec *av, const struct sock *sk,
* We may well decide to do buffer compression, etc, but for now lets
* just drop.
*
- * From Appendix A:
+ * From Appendix A.1.1 (`New Packets'):
*
* Of course, the circular buffer may overflow, either when the
* HC-Sender is sending data at a very high rate, when the
@@ -274,13 +287,13 @@ int dccp_ackvec_add(struct dccp_ackvec *av, const struct sock *sk,
/*
* A.1.2. Old Packets
*
- * When a packet with Sequence Number S arrives, and
- * S <= buf_ackno, the HC-Receiver will scan the table
- * for the byte corresponding to S. (Indexing structures
+ * When a packet with Sequence Number S <= buf_ackno
+ * arrives, the HC-Receiver will scan the table for
+ * the byte corresponding to S. (Indexing structures
* could reduce the complexity of this scan.)
*/
u64 delta = dccp_delta_seqno(ackno, av->dccpav_buf_ackno);
- u8 index = av->dccpav_buf_head;
+ u32 index = av->dccpav_buf_head;
while (1) {
const u8 len = dccp_ackvec_len(av, index);
@@ -322,21 +335,18 @@ out_duplicate:
#ifdef CONFIG_IP_DCCP_DEBUG
void dccp_ackvector_print(const u64 ackno, const unsigned char *vector, int len)
{
- if (!dccp_debug)
- return;
-
- printk("ACK vector len=%d, ackno=%llu |", len,
- (unsigned long long)ackno);
+ dccp_pr_debug_cat("ACK vector len=%d, ackno=%llu |", len,
+ (unsigned long long)ackno);
while (len--) {
const u8 state = (*vector & DCCP_ACKVEC_STATE_MASK) >> 6;
const u8 rl = *vector & DCCP_ACKVEC_LEN_MASK;
- printk("%d,%d|", state, rl);
+ dccp_pr_debug_cat("%d,%d|", state, rl);
++vector;
}
- printk("\n");
+ dccp_pr_debug_cat("\n");
}
void dccp_ackvec_print(const struct dccp_ackvec *av)
@@ -380,24 +390,20 @@ void dccp_ackvec_check_rcv_ackno(struct dccp_ackvec *av, struct sock *sk,
*/
list_for_each_entry_reverse(avr, &av->dccpav_records, dccpavr_node) {
if (ackno == avr->dccpavr_ack_seqno) {
-#ifdef CONFIG_IP_DCCP_DEBUG
- struct dccp_sock *dp = dccp_sk(sk);
- const char *debug_prefix = dp->dccps_role == DCCP_ROLE_CLIENT ?
- "CLIENT rx ack: " : "server rx ack: ";
-#endif
- dccp_pr_debug("%sACK packet 0, len=%d, ack_seqno=%llu, "
+ dccp_pr_debug("%s ACK packet 0, len=%d, ack_seqno=%llu, "
"ack_ackno=%llu, ACKED!\n",
- debug_prefix, 1,
+ dccp_role(sk), 1,
(unsigned long long)avr->dccpavr_ack_seqno,
(unsigned long long)avr->dccpavr_ack_ackno);
dccp_ackvec_throw_record(av, avr);
break;
- }
+ } else if (avr->dccpavr_ack_seqno > ackno)
+ break; /* old news */
}
}
static void dccp_ackvec_check_rcv_ackvector(struct dccp_ackvec *av,
- struct sock *sk, u64 ackno,
+ struct sock *sk, u64 *ackno,
const unsigned char len,
const unsigned char *vector)
{
@@ -420,7 +426,7 @@ static void dccp_ackvec_check_rcv_ackvector(struct dccp_ackvec *av,
const u8 rl = *vector & DCCP_ACKVEC_LEN_MASK;
u64 ackno_end_rl;
- dccp_set_seqno(&ackno_end_rl, ackno - rl);
+ dccp_set_seqno(&ackno_end_rl, *ackno - rl);
/*
* If our AVR sequence number is greater than the ack, go
@@ -428,25 +434,19 @@ static void dccp_ackvec_check_rcv_ackvector(struct dccp_ackvec *av,
*/
list_for_each_entry_from(avr, &av->dccpav_records,
dccpavr_node) {
- if (!after48(avr->dccpavr_ack_seqno, ackno))
+ if (!after48(avr->dccpavr_ack_seqno, *ackno))
goto found;
}
/* End of the dccpav_records list, not found, exit */
break;
found:
- if (between48(avr->dccpavr_ack_seqno, ackno_end_rl, ackno)) {
+ if (between48(avr->dccpavr_ack_seqno, ackno_end_rl, *ackno)) {
const u8 state = *vector & DCCP_ACKVEC_STATE_MASK;
if (state != DCCP_ACKVEC_STATE_NOT_RECEIVED) {
-#ifdef CONFIG_IP_DCCP_DEBUG
- struct dccp_sock *dp = dccp_sk(sk);
- const char *debug_prefix =
- dp->dccps_role == DCCP_ROLE_CLIENT ?
- "CLIENT rx ack: " : "server rx ack: ";
-#endif
- dccp_pr_debug("%sACK vector 0, len=%d, "
+ dccp_pr_debug("%s ACK vector 0, len=%d, "
"ack_seqno=%llu, ack_ackno=%llu, "
"ACKED!\n",
- debug_prefix, len,
+ dccp_role(sk), len,
(unsigned long long)
avr->dccpavr_ack_seqno,
(unsigned long long)
@@ -460,27 +460,23 @@ found:
*/
}
- dccp_set_seqno(&ackno, ackno_end_rl - 1);
+ dccp_set_seqno(ackno, ackno_end_rl - 1);
++vector;
}
}
int dccp_ackvec_parse(struct sock *sk, const struct sk_buff *skb,
- const u8 opt, const u8 *value, const u8 len)
+ u64 *ackno, const u8 opt, const u8 *value, const u8 len)
{
- if (len > DCCP_MAX_ACKVEC_LEN)
+ if (len > DCCP_MAX_ACKVEC_OPT_LEN)
return -1;
/* dccp_ackvector_print(DCCP_SKB_CB(skb)->dccpd_ack_seq, value, len); */
dccp_ackvec_check_rcv_ackvector(dccp_sk(sk)->dccps_hc_rx_ackvec, sk,
- DCCP_SKB_CB(skb)->dccpd_ack_seq,
- len, value);
+ ackno, len, value);
return 0;
}
-static char dccp_ackvec_slab_msg[] __initdata =
- KERN_CRIT "DCCP: Unable to create ack vectors slab caches\n";
-
int __init dccp_ackvec_init(void)
{
dccp_ackvec_slab = kmem_cache_create("dccp_ackvec",
@@ -502,7 +498,7 @@ out_destroy_slab:
kmem_cache_destroy(dccp_ackvec_slab);
dccp_ackvec_slab = NULL;
out_err:
- printk(dccp_ackvec_slab_msg);
+ DCCP_CRIT("Unable to create Ack Vector slab cache");
return -ENOBUFS;
}
diff --git a/net/dccp/ackvec.h b/net/dccp/ackvec.h
index 2424effac7f..96504a3b16e 100644
--- a/net/dccp/ackvec.h
+++ b/net/dccp/ackvec.h
@@ -17,7 +17,9 @@
#include <linux/types.h>
/* Read about the ECN nonce to see why it is 253 */
-#define DCCP_MAX_ACKVEC_LEN 253
+#define DCCP_MAX_ACKVEC_OPT_LEN 253
+/* We can spread an ack vector across multiple options */
+#define DCCP_MAX_ACKVEC_LEN (DCCP_MAX_ACKVEC_OPT_LEN * 2)
#define DCCP_ACKVEC_STATE_RECEIVED 0
#define DCCP_ACKVEC_STATE_ECN_MARKED (1 << 6)
@@ -28,8 +30,7 @@
/** struct dccp_ackvec - ack vector
*
- * This data structure is the one defined in the DCCP draft
- * Appendix A.
+ * This data structure is the one defined in RFC 4340, Appendix A.
*
* @dccpav_buf_head - circular buffer head
* @dccpav_buf_tail - circular buffer tail
@@ -42,7 +43,6 @@
* Ack Vectors it has recently sent. For each packet sent carrying an
* Ack Vector, it remembers four variables:
*
- * @dccpav_ack_ptr - the value of buf_head at the time of acknowledgement.
* @dccpav_records - list of dccp_ackvec_record
* @dccpav_ack_nonce - the one-bit sum of the ECN Nonces for all State 0.
*
@@ -53,9 +53,8 @@ struct dccp_ackvec {
u64 dccpav_buf_ackno;
struct list_head dccpav_records;
struct timeval dccpav_time;
- u8 dccpav_buf_head;
- u8 dccpav_ack_ptr;
- u8 dccpav_vec_len;
+ u16 dccpav_buf_head;
+ u16 dccpav_vec_len;
u8 dccpav_buf_nonce;
u8 dccpav_ack_nonce;
u8 dccpav_buf[DCCP_MAX_ACKVEC_LEN];
@@ -78,9 +77,9 @@ struct dccp_ackvec_record {
struct list_head dccpavr_node;
u64 dccpavr_ack_seqno;
u64 dccpavr_ack_ackno;
- u8 dccpavr_ack_ptr;
+ u16 dccpavr_ack_ptr;
+ u16 dccpavr_sent_len;
u8 dccpavr_ack_nonce;
- u8 dccpavr_sent_len;
};
struct sock;
@@ -99,7 +98,8 @@ extern int dccp_ackvec_add(struct dccp_ackvec *av, const struct sock *sk,
extern void dccp_ackvec_check_rcv_ackno(struct dccp_ackvec *av,
struct sock *sk, const u64 ackno);
extern int dccp_ackvec_parse(struct sock *sk, const struct sk_buff *skb,
- const u8 opt, const u8 *value, const u8 len);
+ u64 *ackno, const u8 opt,
+ const u8 *value, const u8 len);
extern int dccp_insert_option_ackvec(struct sock *sk, struct sk_buff *skb);
@@ -138,7 +138,8 @@ static inline void dccp_ackvec_check_rcv_ackno(struct dccp_ackvec *av,
}
static inline int dccp_ackvec_parse(struct sock *sk, const struct sk_buff *skb,
- const u8 opt, const u8 *value, const u8 len)
+ const u64 *ackno, const u8 opt,
+ const u8 *value, const u8 len)
{
return -1;
}
diff --git a/net/dccp/ccid.h b/net/dccp/ccid.h
index f7eb6c61341..c7c29514dce 100644
--- a/net/dccp/ccid.h
+++ b/net/dccp/ccid.h
@@ -52,9 +52,9 @@ struct ccid_operations {
unsigned char len, u16 idx,
unsigned char* value);
int (*ccid_hc_tx_send_packet)(struct sock *sk,
- struct sk_buff *skb, int len);
- void (*ccid_hc_tx_packet_sent)(struct sock *sk, int more,
- int len);
+ struct sk_buff *skb);
+ void (*ccid_hc_tx_packet_sent)(struct sock *sk,
+ int more, unsigned int len);
void (*ccid_hc_rx_get_info)(struct sock *sk,
struct tcp_info *info);
void (*ccid_hc_tx_get_info)(struct sock *sk,
@@ -94,16 +94,16 @@ extern void ccid_hc_rx_delete(struct ccid *ccid, struct sock *sk);
extern void ccid_hc_tx_delete(struct ccid *ccid, struct sock *sk);
static inline int ccid_hc_tx_send_packet(struct ccid *ccid, struct sock *sk,
- struct sk_buff *skb, int len)
+ struct sk_buff *skb)
{
int rc = 0;
if (ccid->ccid_ops->ccid_hc_tx_send_packet != NULL)
- rc = ccid->ccid_ops->ccid_hc_tx_send_packet(sk, skb, len);
+ rc = ccid->ccid_ops->ccid_hc_tx_send_packet(sk, skb);
return rc;
}
static inline void ccid_hc_tx_packet_sent(struct ccid *ccid, struct sock *sk,
- int more, int len)
+ int more, unsigned int len)
{
if (ccid->ccid_ops->ccid_hc_tx_packet_sent != NULL)
ccid->ccid_ops->ccid_hc_tx_packet_sent(sk, more, len);
diff --git a/net/dccp/ccids/Kconfig b/net/dccp/ccids/Kconfig
index 32752f75044..dac89166eb1 100644
--- a/net/dccp/ccids/Kconfig
+++ b/net/dccp/ccids/Kconfig
@@ -22,19 +22,26 @@ config IP_DCCP_CCID2
for lost packets, would prefer CCID 2 to CCID 3. On-line games may
also prefer CCID 2.
- CCID 2 is further described in:
- http://www.icir.org/kohler/dccp/draft-ietf-dccp-ccid2-10.txt
+ CCID 2 is further described in RFC 4341,
+ http://www.ietf.org/rfc/rfc4341.txt
- This text was extracted from:
- http://www.icir.org/kohler/dccp/draft-ietf-dccp-spec-13.txt
+ 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.
@@ -53,20 +60,33 @@ config IP_DCCP_CCID3
suitable than CCID 2 for applications such streaming media where a
relatively smooth sending rate is of importance.
- CCID 3 is further described in:
-
- http://www.icir.org/kohler/dccp/draft-ietf-dccp-ccid3-11.txt.
+ CCID 3 is further described in RFC 4342,
+ http://www.ietf.org/rfc/rfc4342.txt
The TFRC congestion control algorithms were initially described in
RFC 3448.
- This text was extracted from:
- http://www.icir.org/kohler/dccp/draft-ietf-dccp-spec-13.txt
+ 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
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/ccid2.c b/net/dccp/ccids/ccid2.c
index 2efb505aeb3..2555be8f479 100644
--- a/net/dccp/ccids/ccid2.c
+++ b/net/dccp/ccids/ccid2.c
@@ -23,7 +23,7 @@
*/
/*
- * This implementation should follow: draft-ietf-dccp-ccid2-10.txt
+ * This implementation should follow RFC 4341
*
* BUGS:
* - sequence number wrapping
@@ -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,
@@ -131,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;
@@ -274,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);
@@ -352,14 +345,14 @@ static void ccid2_hc_tx_packet_sent(struct sock *sk, int more, int len)
#ifdef CONFIG_IP_DCCP_CCID2_DEBUG
ccid2_pr_debug("pipe=%d\n", hctx->ccid2hctx_pipe);
- ccid2_pr_debug("Sent: seq=%llu\n", seq);
+ ccid2_pr_debug("Sent: seq=%llu\n", (unsigned long long)seq);
do {
struct ccid2_seq *seqp = hctx->ccid2hctx_seqt;
while (seqp != hctx->ccid2hctx_seqh) {
ccid2_pr_debug("out seq=%llu acked=%d time=%lu\n",
- seqp->ccid2s_seq, seqp->ccid2s_acked,
- seqp->ccid2s_sent);
+ (unsigned long long)seqp->ccid2s_seq,
+ seqp->ccid2s_acked, seqp->ccid2s_sent);
seqp = seqp->ccid2s_next;
}
} while (0);
@@ -426,7 +419,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;
}
@@ -480,7 +473,8 @@ static inline void ccid2_new_ack(struct sock *sk,
/* first measurement */
if (hctx->ccid2hctx_srtt == -1) {
ccid2_pr_debug("R: %lu Time=%lu seq=%llu\n",
- r, jiffies, seqp->ccid2s_seq);
+ r, jiffies,
+ (unsigned long long)seqp->ccid2s_seq);
ccid2_change_srtt(hctx, r);
hctx->ccid2hctx_rttvar = r >> 1;
} else {
@@ -618,7 +612,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.
@@ -636,8 +640,9 @@ static void ccid2_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
u64 ackno_end_rl;
dccp_set_seqno(&ackno_end_rl, ackno - rl);
- ccid2_pr_debug("ackvec start:%llu end:%llu\n", ackno,
- ackno_end_rl);
+ ccid2_pr_debug("ackvec start:%llu end:%llu\n",
+ (unsigned long long)ackno,
+ (unsigned long long)ackno_end_rl);
/* if the seqno we are analyzing is larger than the
* current ackno, then move towards the tail of our
* seqnos.
@@ -672,7 +677,7 @@ static void ccid2_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
seqp->ccid2s_acked = 1;
ccid2_pr_debug("Got ack for %llu\n",
- seqp->ccid2s_seq);
+ (unsigned long long)seqp->ccid2s_seq);
ccid2_hc_tx_dec_pipe(sk);
}
if (seqp == hctx->ccid2hctx_seqt) {
@@ -695,7 +700,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) {
@@ -718,7 +730,7 @@ static void ccid2_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
while (1) {
if (!seqp->ccid2s_acked) {
ccid2_pr_debug("Packet lost: %llu\n",
- seqp->ccid2s_seq);
+ (unsigned long long)seqp->ccid2s_seq);
/* XXX need to traverse from tail -> head in
* order to detect multiple congestion events in
* one ack vector.
@@ -769,6 +781,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;
@@ -821,8 +834,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)
{
diff --git a/net/dccp/ccids/ccid2.h b/net/dccp/ccids/ccid2.h
index 5b2ef4acb30..ebd79499c85 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
@@ -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 {
diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c
index 67d2dc0e7c6..70ebe705eb7 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,15 +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;
-/* 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
+#ifdef CONFIG_IP_DCCP_CCID3_DEBUG
static const char *ccid3_tx_state_name(enum ccid3_hc_tx_states state)
{
static char *ccid3_state_names[] = {
@@ -110,25 +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)
{
- /*
- * 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);
-}
+ timeval_sub_usecs(&hctx->ccid3hctx_t_nom, hctx->ccid3hctx_t_ipi);
-/* 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)
-{
+ /* 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);
+
+ /* 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)
@@ -139,76 +128,85 @@ static inline void ccid3_calc_new_delta(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;
/* To avoid large error in calcX */
if (hctx->ccid3hctx_p >= TFRC_SMALLEST_P) {
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);
+}
+
+/*
+ * Track t