X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=net%2Fdccp%2Fackvec.c;h=2c77dafbd091f9c4627097b037b0a816bf18301e;hb=987b0145d94eecf292d8b301228356f44611ab7c;hp=8c211c58893b2a6de115110743ed33a88befbe4d;hpb=f7ed79d23a47594e7834d66a8f14449796d4f3e6;p=linux-2.6.git diff --git a/net/dccp/ackvec.c b/net/dccp/ackvec.c index 8c211c588..2c77dafbd 100644 --- a/net/dccp/ackvec.c +++ b/net/dccp/ackvec.c @@ -13,83 +13,36 @@ #include "dccp.h" #include -#include -#include -#include #include -#include #include -static kmem_cache_t *dccp_ackvec_slab; -static kmem_cache_t *dccp_ackvec_record_slab; - -static struct dccp_ackvec_record *dccp_ackvec_record_new(void) -{ - struct dccp_ackvec_record *avr = - kmem_cache_alloc(dccp_ackvec_record_slab, GFP_ATOMIC); - - if (avr != NULL) - INIT_LIST_HEAD(&avr->dccpavr_node); - - return avr; -} - -static void dccp_ackvec_record_delete(struct dccp_ackvec_record *avr) -{ - if (unlikely(avr == NULL)) - return; - /* Check if deleting a linked record */ - WARN_ON(!list_empty(&avr->dccpavr_node)); - kmem_cache_free(dccp_ackvec_record_slab, avr); -} - -static void dccp_ackvec_insert_avr(struct dccp_ackvec *av, - struct dccp_ackvec_record *avr) -{ - /* - * AVRs are sorted by seqno. Since we are sending them in order, we - * just add the AVR at the head of the list. - * -sorbo. - */ - if (!list_empty(&av->dccpav_records)) { - const struct dccp_ackvec_record *head = - list_entry(av->dccpav_records.next, - struct dccp_ackvec_record, - dccpavr_node); - BUG_ON(before48(avr->dccpavr_ack_seqno, - head->dccpavr_ack_seqno)); - } - - list_add(&avr->dccpavr_node, &av->dccpav_records); -} - 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; struct timeval now; u32 elapsed_time; unsigned char *to, *from; - struct dccp_ackvec_record *avr; - - if (DCCP_SKB_CB(skb)->dccpd_opt_len + len > DCCP_MAX_OPT_LEN) - return -1; dccp_timestamp(sk, &now); elapsed_time = timeval_delta(&now, &av->dccpav_time) / 10; - if (elapsed_time != 0 && - dccp_insert_option_elapsed_time(sk, skb, elapsed_time)) + if (elapsed_time != 0) + dccp_insert_option_elapsed_time(sk, skb, elapsed_time); + + if (DCCP_SKB_CB(skb)->dccpd_opt_len + len > DCCP_MAX_OPT_LEN) return -1; - avr = dccp_ackvec_record_new(); - if (avr == NULL) + /* + * XXX: now we have just one ack vector sent record, so + * we have to wait for it to be cleared. + * + * Of course this is not acceptable, but this is just for + * basic testing now. + */ + if (av->dccpav_ack_seqno != DCCP_MAX_SEQNO + 1) return -1; DCCP_SKB_CB(skb)->dccpd_opt_len += len; @@ -102,8 +55,8 @@ int dccp_insert_option_ackvec(struct sock *sk, struct sk_buff *skb) from = av->dccpav_buf + av->dccpav_buf_head; /* 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 ((int)av->dccpav_buf_head + len > av->dccpav_vec_len) { + const u32 tailsize = av->dccpav_vec_len - av->dccpav_buf_head; memcpy(to, from, tailsize); to += tailsize; @@ -120,37 +73,45 @@ int dccp_insert_option_ackvec(struct sock *sk, struct sk_buff *skb) * sequence number it used for the ack packet; ack_ptr will equal * buf_head; ack_ackno will equal buf_ackno; and ack_nonce will * equal buf_nonce. + * + * This implemention uses just one ack record for now. */ - avr->dccpavr_ack_seqno = DCCP_SKB_CB(skb)->dccpd_seq; - avr->dccpavr_ack_ptr = av->dccpav_buf_head; - avr->dccpavr_ack_ackno = av->dccpav_buf_ackno; - avr->dccpavr_ack_nonce = av->dccpav_buf_nonce; - avr->dccpavr_sent_len = av->dccpav_vec_len; - - dccp_ackvec_insert_avr(av, avr); + av->dccpav_ack_seqno = DCCP_SKB_CB(skb)->dccpd_seq; + av->dccpav_ack_ptr = av->dccpav_buf_head; + av->dccpav_ack_ackno = av->dccpav_buf_ackno; + av->dccpav_ack_nonce = av->dccpav_buf_nonce; + av->dccpav_sent_len = av->dccpav_vec_len; dccp_pr_debug("%sACK Vector 0, len=%d, ack_seqno=%llu, " "ack_ackno=%llu\n", - debug_prefix, avr->dccpavr_sent_len, - (unsigned long long)avr->dccpavr_ack_seqno, - (unsigned long long)avr->dccpavr_ack_ackno); - return 0; + debug_prefix, av->dccpav_sent_len, + (unsigned long long)av->dccpav_ack_seqno, + (unsigned long long)av->dccpav_ack_ackno); + return -1; } -struct dccp_ackvec *dccp_ackvec_alloc(const gfp_t priority) +struct dccp_ackvec *dccp_ackvec_alloc(const unsigned int len, + const gfp_t priority) { - struct dccp_ackvec *av = kmem_cache_alloc(dccp_ackvec_slab, priority); + struct dccp_ackvec *av; + + BUG_ON(len == 0); + if (len > DCCP_MAX_ACKVEC_LEN) + return NULL; + + av = kmalloc(sizeof(*av) + len, priority); if (av != NULL) { + av->dccpav_buf_len = len; av->dccpav_buf_head = - av->dccpav_buf_tail = DCCP_MAX_ACKVEC_LEN - 1; - av->dccpav_buf_ackno = DCCP_MAX_SEQNO + 1; + av->dccpav_buf_tail = av->dccpav_buf_len - 1; + av->dccpav_buf_ackno = + av->dccpav_ack_ackno = av->dccpav_ack_seqno = ~0LLU; 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_sent_len = av->dccpav_vec_len = 0; - INIT_LIST_HEAD(&av->dccpav_records); } return av; @@ -158,20 +119,7 @@ struct dccp_ackvec *dccp_ackvec_alloc(const gfp_t priority) void dccp_ackvec_free(struct dccp_ackvec *av) { - if (unlikely(av == NULL)) - return; - - if (!list_empty(&av->dccpav_records)) { - struct dccp_ackvec_record *avr, *next; - - list_for_each_entry_safe(avr, next, &av->dccpav_records, - dccpavr_node) { - list_del_init(&avr->dccpavr_node); - dccp_ackvec_record_delete(avr); - } - } - - kmem_cache_free(dccp_ackvec_slab, av); + kfree(av); } static inline u8 dccp_ackvec_state(const struct dccp_ackvec *av, @@ -198,7 +146,7 @@ static inline int dccp_ackvec_set_buf_head_state(struct dccp_ackvec *av, unsigned int gap; long new_head; - if (av->dccpav_vec_len + packets > DCCP_MAX_ACKVEC_LEN) + if (av->dccpav_vec_len + packets > av->dccpav_buf_len) return -ENOBUFS; gap = packets - 1; @@ -210,7 +158,7 @@ static inline int dccp_ackvec_set_buf_head_state(struct dccp_ackvec *av, gap + new_head + 1); gap = -new_head; } - new_head += DCCP_MAX_ACKVEC_LEN; + new_head += av->dccpav_buf_len; } av->dccpav_buf_head = new_head; @@ -303,7 +251,7 @@ int dccp_ackvec_add(struct dccp_ackvec *av, const struct sock *sk, goto out_duplicate; delta -= len + 1; - if (++index == DCCP_MAX_ACKVEC_LEN) + if (++index == av->dccpav_buf_len) index = 0; } } @@ -311,6 +259,7 @@ int dccp_ackvec_add(struct dccp_ackvec *av, const struct sock *sk, av->dccpav_buf_ackno = ackno; dccp_timestamp(sk, &av->dccpav_time); out: + dccp_pr_debug(""); return 0; out_duplicate: @@ -348,50 +297,44 @@ void dccp_ackvec_print(const struct dccp_ackvec *av) } #endif -static void dccp_ackvec_throw_record(struct dccp_ackvec *av, - struct dccp_ackvec_record *avr) +static void dccp_ackvec_throw_away_ack_record(struct dccp_ackvec *av) { - struct dccp_ackvec_record *next; - - av->dccpav_buf_tail = avr->dccpavr_ack_ptr - 1; - if (av->dccpav_buf_tail == 0) - av->dccpav_buf_tail = DCCP_MAX_ACKVEC_LEN - 1; - - av->dccpav_vec_len -= avr->dccpavr_sent_len; - - /* free records */ - list_for_each_entry_safe_from(avr, next, &av->dccpav_records, - dccpavr_node) { - list_del_init(&avr->dccpavr_node); - dccp_ackvec_record_delete(avr); - } + /* + * As we're keeping track of the ack vector size (dccpav_vec_len) and + * the sent ack vector size (dccpav_sent_len) we don't need + * dccpav_buf_tail at all, but keep this code here as in the future + * we'll implement a vector of ack records, as suggested in + * draft-ietf-dccp-spec-11.txt Appendix A. -acme + */ +#if 0 + u32 new_buf_tail = av->dccpav_ack_ptr + 1; + if (new_buf_tail >= av->dccpav_vec_len) + new_buf_tail -= av->dccpav_vec_len; + av->dccpav_buf_tail = new_buf_tail; +#endif + av->dccpav_vec_len -= av->dccpav_sent_len; } void dccp_ackvec_check_rcv_ackno(struct dccp_ackvec *av, struct sock *sk, const u64 ackno) { - struct dccp_ackvec_record *avr; + /* Check if we actually sent an ACK vector */ + if (av->dccpav_ack_seqno == DCCP_MAX_SEQNO + 1) + return; - /* - * If we traverse backwards, it should be faster when we have large - * windows. We will be receiving ACKs for stuff we sent a while back - * -sorbo. - */ - list_for_each_entry_reverse(avr, &av->dccpav_records, dccpavr_node) { - if (ackno == avr->dccpavr_ack_seqno) { + if (ackno == av->dccpav_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: "; + 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, " - "ack_ackno=%llu, ACKED!\n", - debug_prefix, 1, - (unsigned long long)avr->dccpavr_ack_seqno, - (unsigned long long)avr->dccpavr_ack_ackno); - dccp_ackvec_throw_record(av, avr); - break; - } + dccp_pr_debug("%sACK packet 0, len=%d, ack_seqno=%llu, " + "ack_ackno=%llu, ACKED!\n", + debug_prefix, 1, + (unsigned long long)av->dccpav_ack_seqno, + (unsigned long long)av->dccpav_ack_ackno); + dccp_ackvec_throw_away_ack_record(av); + av->dccpav_ack_seqno = DCCP_MAX_SEQNO + 1; } } @@ -401,20 +344,28 @@ static void dccp_ackvec_check_rcv_ackvector(struct dccp_ackvec *av, 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)) + if (av->dccpav_ack_seqno == DCCP_MAX_SEQNO + 1) return; - - i = len; /* - * XXX - * I think it might be more efficient to work backwards. See comment on - * rcv_ackno. -sorbo. + * We're in the receiver half connection, so if the received an ACK + * vector ackno (e.g. 50) before dccpav_ack_seqno (e.g. 52), we're + * not interested. + * + * Extra explanation with example: + * + * if we received an ACK vector with ackno 50, it can only be acking + * 50, 49, 48, etc, not 52 (the seqno for the ACK vector we sent). */ - avr = list_entry(av->dccpav_records.next, struct dccp_ackvec_record, - dccpavr_node); + /* dccp_pr_debug("is %llu < %llu? ", ackno, av->dccpav_ack_seqno); */ + if (before48(ackno, av->dccpav_ack_seqno)) { + /* dccp_pr_debug_cat("yes\n"); */ + return; + } + /* dccp_pr_debug_cat("no\n"); */ + + i = len; while (i--) { const u8 rl = *vector & DCCP_ACKVEC_LEN_MASK; u64 ackno_end_rl; @@ -422,20 +373,14 @@ static void dccp_ackvec_check_rcv_ackvector(struct dccp_ackvec *av, dccp_set_seqno(&ackno_end_rl, ackno - rl); /* - * If our AVR sequence number is greater than the ack, go - * forward in the AVR list until it is not so. + * dccp_pr_debug("is %llu <= %llu <= %llu? ", ackno_end_rl, + * av->dccpav_ack_seqno, ackno); */ - list_for_each_entry_from(avr, &av->dccpav_records, - dccpavr_node) { - 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(av->dccpav_ack_seqno, ackno_end_rl, ackno)) { const u8 state = (*vector & DCCP_ACKVEC_STATE_MASK) >> 6; + /* dccp_pr_debug_cat("yes\n"); */ + if (state != DCCP_ACKVEC_STATE_NOT_RECEIVED) { #ifdef CONFIG_IP_DCCP_DEBUG struct dccp_sock *dp = dccp_sk(sk); @@ -448,17 +393,19 @@ found: "ACKED!\n", debug_prefix, len, (unsigned long long) - avr->dccpavr_ack_seqno, + av->dccpav_ack_seqno, (unsigned long long) - avr->dccpavr_ack_ackno); - dccp_ackvec_throw_record(av, avr); - break; + av->dccpav_ack_ackno); + dccp_ackvec_throw_away_ack_record(av); } /* - * If it wasn't received, continue scanning... we might - * find another one. + * If dccpav_ack_seqno was not received, no problem + * we'll send another ACK vector. */ + av->dccpav_ack_seqno = DCCP_MAX_SEQNO + 1; + break; } + /* dccp_pr_debug_cat("no\n"); */ dccp_set_seqno(&ackno, ackno_end_rl - 1); ++vector; @@ -477,43 +424,3 @@ int dccp_ackvec_parse(struct sock *sk, const struct sk_buff *skb, 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", - sizeof(struct dccp_ackvec), 0, - SLAB_HWCACHE_ALIGN, NULL, NULL); - if (dccp_ackvec_slab == NULL) - goto out_err; - - dccp_ackvec_record_slab = - kmem_cache_create("dccp_ackvec_record", - sizeof(struct dccp_ackvec_record), - 0, SLAB_HWCACHE_ALIGN, NULL, NULL); - if (dccp_ackvec_record_slab == NULL) - goto out_destroy_slab; - - return 0; - -out_destroy_slab: - kmem_cache_destroy(dccp_ackvec_slab); - dccp_ackvec_slab = NULL; -out_err: - printk(dccp_ackvec_slab_msg); - return -ENOBUFS; -} - -void dccp_ackvec_exit(void) -{ - if (dccp_ackvec_slab != NULL) { - kmem_cache_destroy(dccp_ackvec_slab); - dccp_ackvec_slab = NULL; - } - if (dccp_ackvec_record_slab != NULL) { - kmem_cache_destroy(dccp_ackvec_record_slab); - dccp_ackvec_record_slab = NULL; - } -}