Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 111519
b: refs/heads/master
c: c8bf462
h: refs/heads/master
i:
  111517: 050e398
  111515: a8765c3
  111511: 72fa76f
  111503: 66cd132
  111487: 3f1f27b
v: v3
  • Loading branch information
Gerrit Renker committed Sep 4, 2008
1 parent f696894 commit 37e66c7
Show file tree
Hide file tree
Showing 6 changed files with 102 additions and 101 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 5a577b488f687f339dea62e7bb4f4c5793ad523f
refs/heads/master: c8bf462bc567c3dcb083ff95cc13060dd06f138c
28 changes: 28 additions & 0 deletions trunk/net/dccp/ackvec.c
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,34 @@ void dccp_ackvec_clear_state(struct dccp_ackvec *av, const u64 ackno)
}
}

/*
* Routines to keep track of Ack Vectors received in an skb
*/
int dccp_ackvec_parsed_add(struct list_head *head, u8 *vec, u8 len, u8 nonce)
{
struct dccp_ackvec_parsed *new = kmalloc(sizeof(*new), GFP_ATOMIC);

if (new == NULL)
return -ENOBUFS;
new->vec = vec;
new->len = len;
new->nonce = nonce;

list_add_tail(&new->node, head);
return 0;
}
EXPORT_SYMBOL_GPL(dccp_ackvec_parsed_add);

void dccp_ackvec_parsed_cleanup(struct list_head *parsed_chunks)
{
struct dccp_ackvec_parsed *cur, *next;

list_for_each_entry_safe(cur, next, parsed_chunks, node)
kfree(cur);
INIT_LIST_HEAD(parsed_chunks);
}
EXPORT_SYMBOL_GPL(dccp_ackvec_parsed_cleanup);

int __init dccp_ackvec_init(void)
{
dccp_ackvec_slab = kmem_cache_create("dccp_ackvec",
Expand Down
19 changes: 19 additions & 0 deletions trunk/net/dccp/ackvec.h
Original file line number Diff line number Diff line change
Expand Up @@ -114,4 +114,23 @@ static inline bool dccp_ackvec_is_empty(const struct dccp_ackvec *av)
{
return av->av_overflow == 0 && av->av_buf_head == av->av_buf_tail;
}

/**
* struct dccp_ackvec_parsed - Record offsets of Ack Vectors in skb
* @vec: start of vector (offset into skb)
* @len: length of @vec
* @nonce: whether @vec had an ECN nonce of 0 or 1
* @node: FIFO - arranged in descending order of ack_ackno
* This structure is used by CCIDs to access Ack Vectors in a received skb.
*/
struct dccp_ackvec_parsed {
u8 *vec,
len,
nonce:1;
struct list_head node;
};

extern int dccp_ackvec_parsed_add(struct list_head *head,
u8 *vec, u8 len, u8 nonce);
extern void dccp_ackvec_parsed_cleanup(struct list_head *parsed_chunks);
#endif /* _ACKVEC_H */
135 changes: 42 additions & 93 deletions trunk/net/dccp/ccids/ccid2.c
Original file line number Diff line number Diff line change
Expand Up @@ -317,68 +317,6 @@ static void ccid2_hc_tx_packet_sent(struct sock *sk, unsigned int len)
#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)
{
struct ccid2_hc_tx_sock *hctx = ccid2_hc_tx_sk(sk);
Expand Down Expand Up @@ -499,15 +437,27 @@ static void ccid2_congestion_event(struct sock *sk, struct ccid2_seq *seqp)
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)
{
struct dccp_sock *dp = dccp_sk(sk);
struct ccid2_hc_tx_sock *hctx = ccid2_hc_tx_sk(sk);
struct dccp_ackvec_parsed *avp;
u64 ackno, seqno;
struct ccid2_seq *seqp;
unsigned char *vector;
unsigned char veclen;
int offset = 0;
int done = 0;
unsigned int maxincr = 0;

Expand Down Expand Up @@ -542,17 +492,12 @@ static void ccid2_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
}

/* check forward path congestion */
/* still didn't send out new data packets */
if (hctx->seqh == hctx->seqt)
if (dccp_packet_without_ack(skb))
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;
if (after48(ackno, hctx->high_ack))
Expand All @@ -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);

/* 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 */
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_end_rl);
dccp_ackvec_state(avp->vec) >> 6,
dccp_ackvec_runlen(avp->vec));
/* if the seqno we are analyzing is larger than the
* current ackno, then move towards the tail of our
* seqnos.
Expand All @@ -603,7 +549,7 @@ static void ccid2_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
* run length
*/
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 */
if (state != DCCPAV_NOT_RECEIVED &&
Expand All @@ -630,7 +576,6 @@ static void ccid2_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
break;

ackno = SUB48(ackno_end_rl, 1);
vector++;
}
if (done)
break;
Expand Down Expand Up @@ -694,6 +639,8 @@ static void ccid2_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
}

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)
Expand Down Expand Up @@ -727,6 +674,7 @@ static int ccid2_hc_tx_init(struct ccid *ccid, struct sock *sk)
hctx->rpdupack = -1;
hctx->last_cong = jiffies;
setup_timer(&hctx->rtotimer, ccid2_hc_tx_rto_expire, (unsigned long)sk);
INIT_LIST_HEAD(&hctx->av_chunks);

ccid2_hc_tx_check_sanity(hctx);
return 0;
Expand Down Expand Up @@ -762,17 +710,18 @@ static void ccid2_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb)
}

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
Expand Down
2 changes: 2 additions & 0 deletions trunk/net/dccp/ccids/ccid2.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ struct ccid2_seq {
* @lastrtt: time RTT was last measured
* @rpseq: last consecutive seqno
* @rpdupack: dupacks since rpseq
* @av_chunks: list of Ack Vectors received on current skb
*/
struct ccid2_hc_tx_sock {
u32 cwnd;
Expand All @@ -66,6 +67,7 @@ struct ccid2_hc_tx_sock {
int rpdupack;
unsigned long last_cong;
u64 high_ack;
struct list_head av_chunks;
};

struct ccid2_hc_rx_sock {
Expand Down
17 changes: 10 additions & 7 deletions trunk/net/dccp/options.c
Original file line number Diff line number Diff line change
Expand Up @@ -128,13 +128,6 @@ int dccp_parse_options(struct sock *sk, struct dccp_request_sock *dreq,
if (rc)
goto out_featneg_failed;
break;
case DCCPO_ACK_VECTOR_0:
case DCCPO_ACK_VECTOR_1:
if (dccp_packet_without_ack(skb)) /* RFC 4340, 11.4 */
break;
dccp_pr_debug("%s Ack Vector (len=%u)\n", dccp_role(sk),
len);
break;
case DCCPO_TIMESTAMP:
if (len != 4)
goto out_invalid_option;
Expand Down Expand Up @@ -224,6 +217,16 @@ int dccp_parse_options(struct sock *sk, struct dccp_request_sock *dreq,
pkt_type, opt, value, len))
goto out_invalid_option;
break;
case DCCPO_ACK_VECTOR_0:
case DCCPO_ACK_VECTOR_1:
if (dccp_packet_without_ack(skb)) /* RFC 4340, 11.4 */
break;
/*
* Ack vectors are processed by the TX CCID if it is
* interested. The RX CCID need not parse Ack Vectors,
* since it is only interested in clearing old state.
* Fall through.
*/
case DCCPO_MIN_TX_CCID_SPECIFIC ... DCCPO_MAX_TX_CCID_SPECIFIC:
if (ccid_hc_tx_parse_options(dp->dccps_hc_tx_ccid, sk,
pkt_type, opt, value, len))
Expand Down

0 comments on commit 37e66c7

Please sign in to comment.