|
@@ -317,68 +317,6 @@ static void ccid2_hc_tx_packet_sent(struct sock *sk, unsigned int len)
|
|
#endif
|
|
#endif
|
|
}
|
|
}
|
|
|
|
|
|
-/* XXX Lame code duplication!
|
|
|
|
- * returns -1 if none was found.
|
|
|
|
- * else returns the next offset to use in the function call.
|
|
|
|
- */
|
|
|
|
-static int ccid2_ackvector(struct sock *sk, struct sk_buff *skb, int offset,
|
|
|
|
- unsigned char **vec, unsigned char *veclen)
|
|
|
|
-{
|
|
|
|
- const struct dccp_hdr *dh = dccp_hdr(skb);
|
|
|
|
- unsigned char *options = (unsigned char *)dh + dccp_hdr_len(skb);
|
|
|
|
- unsigned char *opt_ptr;
|
|
|
|
- const unsigned char *opt_end = (unsigned char *)dh +
|
|
|
|
- (dh->dccph_doff * 4);
|
|
|
|
- unsigned char opt, len;
|
|
|
|
- unsigned char *value;
|
|
|
|
-
|
|
|
|
- BUG_ON(offset < 0);
|
|
|
|
- options += offset;
|
|
|
|
- opt_ptr = options;
|
|
|
|
- if (opt_ptr >= opt_end)
|
|
|
|
- return -1;
|
|
|
|
-
|
|
|
|
- while (opt_ptr != opt_end) {
|
|
|
|
- opt = *opt_ptr++;
|
|
|
|
- len = 0;
|
|
|
|
- value = NULL;
|
|
|
|
-
|
|
|
|
- /* Check if this isn't a single byte option */
|
|
|
|
- if (opt > DCCPO_MAX_RESERVED) {
|
|
|
|
- if (opt_ptr == opt_end)
|
|
|
|
- goto out_invalid_option;
|
|
|
|
-
|
|
|
|
- len = *opt_ptr++;
|
|
|
|
- if (len < 3)
|
|
|
|
- goto out_invalid_option;
|
|
|
|
- /*
|
|
|
|
- * Remove the type and len fields, leaving
|
|
|
|
- * just the value size
|
|
|
|
- */
|
|
|
|
- len -= 2;
|
|
|
|
- value = opt_ptr;
|
|
|
|
- opt_ptr += len;
|
|
|
|
-
|
|
|
|
- if (opt_ptr > opt_end)
|
|
|
|
- goto out_invalid_option;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- switch (opt) {
|
|
|
|
- case DCCPO_ACK_VECTOR_0:
|
|
|
|
- case DCCPO_ACK_VECTOR_1:
|
|
|
|
- *vec = value;
|
|
|
|
- *veclen = len;
|
|
|
|
- return offset + (opt_ptr - options);
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- return -1;
|
|
|
|
-
|
|
|
|
-out_invalid_option:
|
|
|
|
- DCCP_BUG("Invalid option - this should not happen (previous parsing)!");
|
|
|
|
- return -1;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
static void ccid2_hc_tx_kill_rto_timer(struct sock *sk)
|
|
static void ccid2_hc_tx_kill_rto_timer(struct sock *sk)
|
|
{
|
|
{
|
|
struct ccid2_hc_tx_sock *hctx = ccid2_hc_tx_sk(sk);
|
|
struct ccid2_hc_tx_sock *hctx = ccid2_hc_tx_sk(sk);
|
|
@@ -499,15 +437,27 @@ static void ccid2_congestion_event(struct sock *sk, struct ccid2_seq *seqp)
|
|
ccid2_change_l_ack_ratio(sk, hctx->cwnd);
|
|
ccid2_change_l_ack_ratio(sk, hctx->cwnd);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static int ccid2_hc_tx_parse_options(struct sock *sk, u8 packet_type,
|
|
|
|
+ u8 option, u8 *optval, u8 optlen)
|
|
|
|
+{
|
|
|
|
+ struct ccid2_hc_tx_sock *hctx = ccid2_hc_tx_sk(sk);
|
|
|
|
+
|
|
|
|
+ switch (option) {
|
|
|
|
+ case DCCPO_ACK_VECTOR_0:
|
|
|
|
+ case DCCPO_ACK_VECTOR_1:
|
|
|
|
+ return dccp_ackvec_parsed_add(&hctx->av_chunks, optval, optlen,
|
|
|
|
+ option - DCCPO_ACK_VECTOR_0);
|
|
|
|
+ }
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+
|
|
static void ccid2_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
|
|
static void ccid2_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
|
|
{
|
|
{
|
|
struct dccp_sock *dp = dccp_sk(sk);
|
|
struct dccp_sock *dp = dccp_sk(sk);
|
|
struct ccid2_hc_tx_sock *hctx = ccid2_hc_tx_sk(sk);
|
|
struct ccid2_hc_tx_sock *hctx = ccid2_hc_tx_sk(sk);
|
|
|
|
+ struct dccp_ackvec_parsed *avp;
|
|
u64 ackno, seqno;
|
|
u64 ackno, seqno;
|
|
struct ccid2_seq *seqp;
|
|
struct ccid2_seq *seqp;
|
|
- unsigned char *vector;
|
|
|
|
- unsigned char veclen;
|
|
|
|
- int offset = 0;
|
|
|
|
int done = 0;
|
|
int done = 0;
|
|
unsigned int maxincr = 0;
|
|
unsigned int maxincr = 0;
|
|
|
|
|
|
@@ -542,17 +492,12 @@ static void ccid2_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
|
|
}
|
|
}
|
|
|
|
|
|
/* check forward path congestion */
|
|
/* check forward path congestion */
|
|
- /* still didn't send out new data packets */
|
|
|
|
- if (hctx->seqh == hctx->seqt)
|
|
|
|
|
|
+ if (dccp_packet_without_ack(skb))
|
|
return;
|
|
return;
|
|
|
|
|
|
- switch (DCCP_SKB_CB(skb)->dccpd_type) {
|
|
|
|
- case DCCP_PKT_ACK:
|
|
|
|
- case DCCP_PKT_DATAACK:
|
|
|
|
- break;
|
|
|
|
- default:
|
|
|
|
- return;
|
|
|
|
- }
|
|
|
|
|
|
+ /* still didn't send out new data packets */
|
|
|
|
+ if (hctx->seqh == hctx->seqt)
|
|
|
|
+ goto done;
|
|
|
|
|
|
ackno = DCCP_SKB_CB(skb)->dccpd_ack_seq;
|
|
ackno = DCCP_SKB_CB(skb)->dccpd_ack_seq;
|
|
if (after48(ackno, hctx->high_ack))
|
|
if (after48(ackno, hctx->high_ack))
|
|
@@ -576,15 +521,16 @@ static void ccid2_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
|
|
maxincr = DIV_ROUND_UP(dp->dccps_l_ack_ratio, 2);
|
|
maxincr = DIV_ROUND_UP(dp->dccps_l_ack_ratio, 2);
|
|
|
|
|
|
/* go through all ack vectors */
|
|
/* go through all ack vectors */
|
|
- while ((offset = ccid2_ackvector(sk, skb, offset,
|
|
|
|
- &vector, &veclen)) != -1) {
|
|
|
|
|
|
+ list_for_each_entry(avp, &hctx->av_chunks, node) {
|
|
/* go through this ack vector */
|
|
/* go through this ack vector */
|
|
- while (veclen--) {
|
|
|
|
- u64 ackno_end_rl = SUB48(ackno, dccp_ackvec_runlen(vector));
|
|
|
|
|
|
+ for (; avp->len--; avp->vec++) {
|
|
|
|
+ u64 ackno_end_rl = SUB48(ackno,
|
|
|
|
+ dccp_ackvec_runlen(avp->vec));
|
|
|
|
|
|
- ccid2_pr_debug("ackvec start:%llu end:%llu\n",
|
|
|
|
|
|
+ ccid2_pr_debug("ackvec %llu |%u,%u|\n",
|
|
(unsigned long long)ackno,
|
|
(unsigned long long)ackno,
|
|
- (unsigned long long)ackno_end_rl);
|
|
|
|
|
|
+ dccp_ackvec_state(avp->vec) >> 6,
|
|
|
|
+ dccp_ackvec_runlen(avp->vec));
|
|
/* if the seqno we are analyzing is larger than the
|
|
/* if the seqno we are analyzing is larger than the
|
|
* current ackno, then move towards the tail of our
|
|
* current ackno, then move towards the tail of our
|
|
* seqnos.
|
|
* seqnos.
|
|
@@ -603,7 +549,7 @@ static void ccid2_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
|
|
* run length
|
|
* run length
|
|
*/
|
|
*/
|
|
while (between48(seqp->ccid2s_seq,ackno_end_rl,ackno)) {
|
|
while (between48(seqp->ccid2s_seq,ackno_end_rl,ackno)) {
|
|
- const u8 state = dccp_ackvec_state(vector);
|
|
|
|
|
|
+ const u8 state = dccp_ackvec_state(avp->vec);
|
|
|
|
|
|
/* new packet received or marked */
|
|
/* new packet received or marked */
|
|
if (state != DCCPAV_NOT_RECEIVED &&
|
|
if (state != DCCPAV_NOT_RECEIVED &&
|
|
@@ -630,7 +576,6 @@ static void ccid2_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
|
|
break;
|
|
break;
|
|
|
|
|
|
ackno = SUB48(ackno_end_rl, 1);
|
|
ackno = SUB48(ackno_end_rl, 1);
|
|
- vector++;
|
|
|
|
}
|
|
}
|
|
if (done)
|
|
if (done)
|
|
break;
|
|
break;
|
|
@@ -694,6 +639,8 @@ static void ccid2_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
|
|
}
|
|
}
|
|
|
|
|
|
ccid2_hc_tx_check_sanity(hctx);
|
|
ccid2_hc_tx_check_sanity(hctx);
|
|
|
|
+done:
|
|
|
|
+ dccp_ackvec_parsed_cleanup(&hctx->av_chunks);
|
|
}
|
|
}
|
|
|
|
|
|
static int ccid2_hc_tx_init(struct ccid *ccid, struct sock *sk)
|
|
static int ccid2_hc_tx_init(struct ccid *ccid, struct sock *sk)
|
|
@@ -727,6 +674,7 @@ static int ccid2_hc_tx_init(struct ccid *ccid, struct sock *sk)
|
|
hctx->rpdupack = -1;
|
|
hctx->rpdupack = -1;
|
|
hctx->last_cong = jiffies;
|
|
hctx->last_cong = jiffies;
|
|
setup_timer(&hctx->rtotimer, ccid2_hc_tx_rto_expire, (unsigned long)sk);
|
|
setup_timer(&hctx->rtotimer, ccid2_hc_tx_rto_expire, (unsigned long)sk);
|
|
|
|
+ INIT_LIST_HEAD(&hctx->av_chunks);
|
|
|
|
|
|
ccid2_hc_tx_check_sanity(hctx);
|
|
ccid2_hc_tx_check_sanity(hctx);
|
|
return 0;
|
|
return 0;
|
|
@@ -762,17 +710,18 @@ static void ccid2_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb)
|
|
}
|
|
}
|
|
|
|
|
|
static struct ccid_operations ccid2 = {
|
|
static struct ccid_operations ccid2 = {
|
|
- .ccid_id = DCCPC_CCID2,
|
|
|
|
- .ccid_name = "TCP-like",
|
|
|
|
- .ccid_owner = THIS_MODULE,
|
|
|
|
- .ccid_hc_tx_obj_size = sizeof(struct ccid2_hc_tx_sock),
|
|
|
|
- .ccid_hc_tx_init = ccid2_hc_tx_init,
|
|
|
|
- .ccid_hc_tx_exit = ccid2_hc_tx_exit,
|
|
|
|
- .ccid_hc_tx_send_packet = ccid2_hc_tx_send_packet,
|
|
|
|
- .ccid_hc_tx_packet_sent = ccid2_hc_tx_packet_sent,
|
|
|
|
- .ccid_hc_tx_packet_recv = ccid2_hc_tx_packet_recv,
|
|
|
|
- .ccid_hc_rx_obj_size = sizeof(struct ccid2_hc_rx_sock),
|
|
|
|
- .ccid_hc_rx_packet_recv = ccid2_hc_rx_packet_recv,
|
|
|
|
|
|
+ .ccid_id = DCCPC_CCID2,
|
|
|
|
+ .ccid_name = "TCP-like",
|
|
|
|
+ .ccid_owner = THIS_MODULE,
|
|
|
|
+ .ccid_hc_tx_obj_size = sizeof(struct ccid2_hc_tx_sock),
|
|
|
|
+ .ccid_hc_tx_init = ccid2_hc_tx_init,
|
|
|
|
+ .ccid_hc_tx_exit = ccid2_hc_tx_exit,
|
|
|
|
+ .ccid_hc_tx_send_packet = ccid2_hc_tx_send_packet,
|
|
|
|
+ .ccid_hc_tx_packet_sent = ccid2_hc_tx_packet_sent,
|
|
|
|
+ .ccid_hc_tx_parse_options = ccid2_hc_tx_parse_options,
|
|
|
|
+ .ccid_hc_tx_packet_recv = ccid2_hc_tx_packet_recv,
|
|
|
|
+ .ccid_hc_rx_obj_size = sizeof(struct ccid2_hc_rx_sock),
|
|
|
|
+ .ccid_hc_rx_packet_recv = ccid2_hc_rx_packet_recv,
|
|
};
|
|
};
|
|
|
|
|
|
#ifdef CONFIG_IP_DCCP_CCID2_DEBUG
|
|
#ifdef CONFIG_IP_DCCP_CCID2_DEBUG
|