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

Reply via email to