ack vectors grow proportional to the window size. If an ack vector does not fit
into a single option, it must be spread across multiple options. This patch
will allow for windows to grow larger.
Signed-off-by: Andrea Bittau <[EMAIL PROTECTED]>
---
diff --git a/net/dccp/ackvec.c b/net/dccp/ackvec.c
index 4d176d3..35308cf 100644
--- a/net/dccp/ackvec.c
+++ b/net/dccp/ackvec.c
@@ -72,11 +72,18 @@ #ifdef CONFIG_IP_DCCP_DEBUG
"CLIENT tx: " : "server tx: ";
#endif
struct dccp_ackvec *av = dp->dccps_hc_rx_ackvec;
- int len = av->dccpav_vec_len + 2;
+ int len;
struct timeval now;
u32 elapsed_time;
unsigned char *to, *from;
struct dccp_ackvec_record *avr;
+ int optc, i;
+
+ /* Figure out how many options do we need to represent the ackvec */
+ optc = av->dccpav_vec_len / DCCP_MAX_ACKVEC_OPT_LEN;
+ if (av->dccpav_vec_len % DCCP_MAX_ACKVEC_OPT_LEN)
+ optc++;
+ len = optc*2 + av->dccpav_vec_len;
if (DCCP_SKB_CB(skb)->dccpd_opt_len + len > DCCP_MAX_OPT_LEN)
return -1;
@@ -94,24 +101,42 @@ #endif
DCCP_SKB_CB(skb)->dccpd_opt_len += len;
- to = skb_push(skb, len);
- *to++ = DCCPO_ACK_VECTOR_0;
- *to++ = len;
-
- len = av->dccpav_vec_len;
+ to = skb_push(skb, len);
from = av->dccpav_buf + av->dccpav_buf_head;
+ len = av->dccpav_vec_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;
+ /* write the vectors */
+ for (i = 0; i < optc; i++) {
+ int copylen = len;
+ if (copylen > DCCP_MAX_ACKVEC_OPT_LEN)
+ copylen = DCCP_MAX_ACKVEC_OPT_LEN;
- memcpy(to, from, tailsize);
- to += tailsize;
- len -= tailsize;
- from = av->dccpav_buf;
+ *to++ = DCCPO_ACK_VECTOR_0;
+ *to++ = copylen+2;
+
+ /* Check if buf_head wraps */
+ if ((from + copylen) > &av->dccpav_buf[DCCP_MAX_ACKVEC_LEN]) {
+ u32 tailsize = &av->dccpav_buf[DCCP_MAX_ACKVEC_LEN] -
+ from;
+
+ memcpy(to, from, tailsize);
+ to += tailsize;
+ from = av->dccpav_buf;
+ copylen -= tailsize;
+ len -= tailsize;
+
+ BUG_ON((from + copylen) >
+ &av->dccpav_buf[DCCP_MAX_ACKVEC_LEN]);
+ }
+
+ memcpy(to, from, copylen);
+ to += copylen;
+ from += copylen;
+
+ len -= copylen;
}
+ BUG_ON(len != 0);
- memcpy(to, from, len);
/*
* From draft-ietf-dccp-spec-11.txt:
*
@@ -145,7 +170,6 @@ struct dccp_ackvec *dccp_ackvec_alloc(co
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 +198,13 @@ void dccp_ackvec_free(struct dccp_ackvec
}
static inline u8 dccp_ackvec_state(const struct dccp_ackvec *av,
- const u8 index)
+ const int 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 int index)
{
return av->dccpav_buf[index] & DCCP_ACKVEC_LEN_MASK;
}
@@ -280,7 +304,7 @@ int dccp_ackvec_add(struct dccp_ackvec *
* could reduce the complexity of this scan.)
*/
u64 delta = dccp_delta_seqno(ackno, av->dccpav_buf_ackno);
- u8 index = av->dccpav_buf_head;
+ int index = av->dccpav_buf_head;
while (1) {
const u8 len = dccp_ackvec_len(av, index);
@@ -396,17 +420,17 @@ #endif
}
}
-static void dccp_ackvec_check_rcv_ackvector(struct dccp_ackvec *av,
- struct sock *sk, u64 ackno,
- const unsigned char len,
- const unsigned char *vector)
+static u64 dccp_ackvec_check_rcv_ackvector(struct dccp_ackvec *av,
+ struct sock *sk, u64 ackno,
+ const unsigned char len,
+ const unsigned char *vector)
{
unsigned char i;
struct dccp_ackvec_record *avr;
/* Check if we actually sent an ACK vector */
if (list_empty(&av->dccpav_records))
- return;
+ return ackno; /* It's OK, because we will always return */
i = len;
/*
@@ -432,7 +456,10 @@ static void dccp_ackvec_check_rcv_ackvec
goto found;
}
/* End of the dccpav_records list, not found, exit */
- break;
+ break; /* Do not need to return a correct ackno because the next
+ * batch of ackvectors will not make situation better
+ * (their acknos will be lower)
+ */
found:
if (between48(avr->dccpavr_ack_seqno, ackno_end_rl, ackno)) {
const u8 state = *vector & DCCP_ACKVEC_STATE_MASK;
@@ -452,7 +479,9 @@ #endif
(unsigned long long)
avr->dccpavr_ack_ackno);
dccp_ackvec_throw_record(av, avr);
- break;
+ break; /* Don't care about other ACKs because we
+ * released the most possible state
+ */
}
/*
* If it wasn't received, continue scanning... we might
@@ -463,19 +492,16 @@ #endif
dccp_set_seqno(&ackno, ackno_end_rl - 1);
++vector;
}
+
+ return ackno;
}
-int dccp_ackvec_parse(struct sock *sk, const struct sk_buff *skb,
+u64 dccp_ackvec_parse(struct sock *sk, u64 ackno,
const u8 opt, const u8 *value, const u8 len)
{
- if (len > DCCP_MAX_ACKVEC_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);
- return 0;
+ return dccp_ackvec_check_rcv_ackvector(dccp_sk(sk)->dccps_hc_rx_ackvec,
+ sk, ackno, len, value);
}
static char dccp_ackvec_slab_msg[] __initdata =
diff --git a/net/dccp/ackvec.h b/net/dccp/ackvec.h
index ec9a988..691a7f4 100644
--- a/net/dccp/ackvec.h
+++ b/net/dccp/ackvec.h
@@ -18,7 +18,9 @@ #include <linux/time.h>
#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)
@@ -54,9 +56,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;
+ int dccpav_buf_head;
+ int dccpav_vec_len;
u8 dccpav_buf_nonce;
u8 dccpav_ack_nonce;
u8 dccpav_buf[DCCP_MAX_ACKVEC_LEN];
@@ -79,9 +80,9 @@ struct dccp_ackvec_record {
struct list_head dccpavr_node;
u64 dccpavr_ack_seqno;
u64 dccpavr_ack_ackno;
- u8 dccpavr_ack_ptr;
+ int dccpavr_ack_ptr;
u8 dccpavr_ack_nonce;
- u8 dccpavr_sent_len;
+ int dccpavr_sent_len;
};
struct sock;
@@ -99,7 +100,7 @@ extern int dccp_ackvec_add(struct dccp_a
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,
+extern u64 dccp_ackvec_parse(struct sock *sk, u64 ackno,
const u8 opt, const u8 *value, const u8 len);
extern int dccp_insert_option_ackvec(struct sock *sk, struct sk_buff *skb);
diff --git a/net/dccp/ccids/ccid2.h b/net/dccp/ccids/ccid2.h
index d208657..5f3e1c8 100644
--- a/net/dccp/ccids/ccid2.h
+++ b/net/dccp/ccids/ccid2.h
@@ -70,7 +70,7 @@ struct ccid2_txprofile {
unsigned long ccid2txp_packets_last;
};
-#define CCID2_SEQBUF_LEN 256
+#define CCID2_SEQBUF_LEN 1024
#define CCID2_SEQBUF_MAX 128
/** struct ccid2_hc_tx_sock - CCID2 TX half connection
diff --git a/net/dccp/dccp.h b/net/dccp/dccp.h
index 1fe5091..303a75a 100644
--- a/net/dccp/dccp.h
+++ b/net/dccp/dccp.h
@@ -42,7 +42,7 @@ extern void dccp_tw_deschedule(struct in
extern void dccp_time_wait(struct sock *sk, int state, int timeo);
/* FIXME: Right size this */
-#define DCCP_MAX_OPT_LEN 128
+#define DCCP_MAX_OPT_LEN 1024
#define DCCP_MAX_PACKET_HDR 32
diff --git a/net/dccp/options.c b/net/dccp/options.c
index e9feb2a..7817313 100644
--- a/net/dccp/options.c
+++ b/net/dccp/options.c
@@ -75,6 +75,7 @@ #endif
u32 elapsed_time;
int rc;
int mandatory = 0;
+ u64 ackno = DCCP_SKB_CB(skb)->dccpd_ack_seq;
memset(opt_recv, 0, sizeof(*opt_recv));
@@ -151,9 +152,9 @@ #endif
if (pkt_type == DCCP_PKT_DATA)
break;
- if (dccp_msk(sk)->dccpms_send_ack_vector &&
- dccp_ackvec_parse(sk, skb, opt, value, len))
- goto out_invalid_option;
+ if (dccp_msk(sk)->dccpms_send_ack_vector)
+ ackno = dccp_ackvec_parse(sk, ackno, opt,
+ value, len);
break;
case DCCPO_TIMESTAMP:
if (len != 4)
-
To unsubscribe from this list: send the line "unsubscribe dccp" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at http://vger.kernel.org/majordomo-info.html