Will review/merge this one today, thanks!

- Arnaldo

PS.: always CC [email protected] on patch submissions, please :)

On 2/16/06, Andrea Bittau <[EMAIL PROTECTED]> wrote:
> Support for multi-byte feature values & change of ACK ratios upon negotiation.
>
> Features of multiple bytes may now be negotiated [such as ACK ratios which are
> 16 bits].  ACK ratios are adjusted upon negotiation.
>
> Signed-off-by: Andrea Bittau <[EMAIL PROTECTED]>
>
> ---
>
> diff --git a/include/linux/dccp.h b/include/linux/dccp.h
> index bdd756c..4d47d01 100644
> --- a/include/linux/dccp.h
> +++ b/include/linux/dccp.h
> @@ -329,7 +329,8 @@ static inline unsigned int dccp_hdr_len(
>
>  /* initial values for each feature */
>  #define DCCPF_INITIAL_SEQUENCE_WINDOW          100
> -#define DCCPF_INITIAL_ACK_RATIO                        2
> +/* FIXME: should be 2, but I still need to think about it */
> +#define DCCPF_INITIAL_ACK_RATIO                        1
>
>  #if defined(CONFIG_IP_DCCP_CCID2) || defined(CONFIG_IP_DCCP_CCID2_MODULE)
>  #define DCCPF_INITIAL_CCID                     2
> @@ -354,12 +355,13 @@ static inline unsigned int dccp_hdr_len(
>    *    @dccpo_send_ndp_count - Send NDP Count Feature (7.7.2)
>    */
>  struct dccp_options {
> -       __u64   dccpo_sequence_window;
> -       __u8    dccpo_rx_ccid;
> -       __u8    dccpo_tx_ccid;
> -       __u8    dccpo_send_ack_vector;
> -       __u8    dccpo_send_ndp_count;
> -       __u8                    dccpo_ack_ratio;
> +       __u64                   dccpo_sequence_window;
> +       __u8                    dccpo_rx_ccid;
> +       __u8                    dccpo_tx_ccid;
> +       __u8                    dccpo_send_ack_vector;
> +       __u8                    dccpo_send_ndp_count;
> +       __u16                   dccpo_l_ack_ratio;
> +       __u16                   dccpo_r_ack_ratio;
>         struct list_head        dccpo_pending;
>         struct list_head        dccpo_conf;
>  };
> @@ -375,6 +377,7 @@ struct dccp_opt_pend {
>         __u8                    dccpop_feat;
>         __u8                    *dccpop_val;
>         __u8                    dccpop_len;
> +       __u8                    dccpop_optlen;
>         int                     dccpop_conf;
>         struct dccp_opt_conf    *dccpop_sc;
>  };
> @@ -472,8 +475,6 @@ struct dccp_sock {
>         struct timeval                  dccps_timestamp_time;
>         __u32                           dccps_timestamp_echo;
>         __u32                           dccps_packet_size;
> -       __u16                           dccps_l_ack_ratio;
> -       __u16                           dccps_r_ack_ratio;
>         unsigned long                   dccps_ndp_count;
>         __u32                           dccps_mss_cache;
>         struct dccp_options             dccps_options;
> diff --git a/net/dccp/ccids/ccid2.c b/net/dccp/ccids/ccid2.c
> index 8f964dc..3fed24a 100644
> --- a/net/dccp/ccids/ccid2.c
> +++ b/net/dccp/ccids/ccid2.c
> @@ -33,6 +33,7 @@
>  #include <linux/config.h>
>  #include "../ccid.h"
>  #include "../dccp.h"
> +#include "../feat.h"
>  #include "ccid2.h"
>
>  static int ccid2_debug;
> @@ -142,9 +143,12 @@ static int ccid2_hc_tx_send_packet(struc
>         return 100; /* XXX */
>  }
>
> -static void ccid2_change_l_ack_ratio(struct sock *sk, int val)
> +static u16 ccid2_change_l_ack_ratio(struct sock *sk, u16 val)
>  {
>         struct dccp_sock *dp = dccp_sk(sk);
> +       u8  *v;
> +       u16 ar;
> +
>         /*
>          * XXX I don't really agree with val != 2.  If cwnd is 1, ack ratio
>          * should be 1... it shouldn't be allowed to become 2.
> @@ -162,9 +166,25 @@ static void ccid2_change_l_ack_ratio(str
>                         val = max;
>         }
>
> +       BUG_ON(val == 0);
> +       /* no change */
> +       if (dp->dccps_options.dccpo_l_ack_ratio == val)
> +               return val;
> +
>         ccid2_pr_debug("changing local ack ratio to %d\n", val);
> -       WARN_ON(val <= 0);
> -       dp->dccps_l_ack_ratio = val;
> +
> +       /* XXX it would be better to replace the old value of the feature, and
> +        * not allocate memory on each change
> +        */
> +       v = kmalloc(sizeof(ar), GFP_ATOMIC);
> +       if (!v)
> +               return val;
> +
> +       ar = htons(val);
> +       memcpy(v, &ar, sizeof(ar));
> +       dccp_feat_change(sk, DCCPO_CHANGE_L, DCCPF_ACK_RATIO,
> +                        v, sizeof(ar), GFP_ATOMIC);
> +       return val;
>  }
>
>  static void ccid2_change_cwnd(struct sock *sk, int val)
> @@ -294,17 +314,18 @@ static void ccid2_hc_tx_packet_sent(stru
>         }
>         /* No acks lost up to now... */
>         else {
> +               u16 ack_ratio = ntohs(dp->dccps_options.dccpo_l_ack_ratio);
> +
>                 /* decrease ack ratio if enough packets were sent */
> -               if (dp->dccps_l_ack_ratio > 1) {
> +               if (ack_ratio > 1) {
>                         /* XXX don't calculate denominator each time */
>                         int denom;
>
> -                       denom = dp->dccps_l_ack_ratio * dp->dccps_l_ack_ratio 
> -
> -                               dp->dccps_l_ack_ratio;
> +                       denom = ack_ratio * ack_ratio - ack_ratio;
>                         denom = hctx->ccid2hctx_cwnd * hctx->ccid2hctx_cwnd / 
> denom;
>
>                         if (hctx->ccid2hctx_arsent >= denom) {
> -                               ccid2_change_l_ack_ratio(sk, 
> dp->dccps_l_ack_ratio - 1);
> +                               ccid2_change_l_ack_ratio(sk, ack_ratio - 1);
>                                 hctx->ccid2hctx_arsent = 0;
>                         }
>                 }
> @@ -525,6 +546,7 @@ static void ccid2_hc_tx_packet_recv(stru
>         int done = 0;
>         int loss = 0;
>         unsigned int maxincr = 0;
> +       u16 ack_ratio = ntohs(dp->dccps_options.dccpo_l_ack_ratio);
>
>         ccid2_hc_tx_check_sanity(hctx);
>         /* check reverse path congestion */
> @@ -555,7 +577,9 @@ static void ccid2_hc_tx_packet_recv(stru
>                                 hctx->ccid2hctx_rpdupack = -1; /* XXX lame */
>                                 hctx->ccid2hctx_rpseq = 0;
>
> -                               ccid2_change_l_ack_ratio(sk, 
> dp->dccps_l_ack_ratio << 1);
> +                               ack_ratio <<= 1;
> +                               ack_ratio = ccid2_change_l_ack_ratio(sk,
> +                                                                    
> ack_ratio);
>                         }
>                 }
>         }
> @@ -581,7 +605,7 @@ static void ccid2_hc_tx_packet_recv(stru
>          * this single ack.  I round up.
>          * -sorbo.
>          */
> -       maxincr = dp->dccps_l_ack_ratio >> 1;
> +       maxincr = ack_ratio >> 1;
>         maxincr++;
>
>         /* go through all ack vectors */
> @@ -765,12 +789,13 @@ static void ccid2_hc_rx_packet_recv(stru
>  {
>         const struct dccp_sock *dp = dccp_sk(sk);
>         struct ccid2_hc_rx_sock *hcrx = ccid2_hc_rx_sk(sk);
> +       u16 ack_ratio = ntohs(dp->dccps_options.dccpo_r_ack_ratio);
>
>         switch (DCCP_SKB_CB(skb)->dccpd_type) {
>         case DCCP_PKT_DATA:
>         case DCCP_PKT_DATAACK:
>                 hcrx->ccid2hcrx_data++;
> -               if (hcrx->ccid2hcrx_data >= dp->dccps_r_ack_ratio) {
> +               if (hcrx->ccid2hcrx_data >= ack_ratio) {
>                         dccp_send_ack(sk);
>                         hcrx->ccid2hcrx_data = 0;
>                 }
> diff --git a/net/dccp/feat.c b/net/dccp/feat.c
> index 641f8af..af96049 100644
> --- a/net/dccp/feat.c
> +++ b/net/dccp/feat.c
> @@ -90,6 +90,22 @@ int dccp_feat_change(struct sock *sk, u8
>         opt->dccpop_conf = 0;
>         opt->dccpop_sc   = NULL;
>
> +       /* determine the length of an individual feature value */
> +       switch(opt->dccpop_feat) {
> +       case DCCPF_CCID:
> +               opt->dccpop_optlen = 1;
> +               break;
> +
> +       case DCCPF_ACK_RATIO:
> +               opt->dccpop_optlen = 2;
> +               break;
> +
> +       default:
> +               opt->dccpop_optlen = 0;
> +               BUG_ON(1); /* XXX implement */
> +               break;
> +       }
> +
>         BUG_ON(opt->dccpop_val == NULL);
>
>         list_add_tail(&opt->dccpop_node, &dp->dccps_options.dccpo_pending);
> @@ -98,6 +114,18 @@ int dccp_feat_change(struct sock *sk, u8
>
>  EXPORT_SYMBOL_GPL(dccp_feat_change);
>
> +static int dccp_feat_update_ar(struct sock *sk, u8 type, u16 ar)
> +{
> +       struct dccp_sock *dp = dccp_sk(sk);
> +
> +       if (type == DCCPO_CHANGE_L)
> +               dp->dccps_options.dccpo_l_ack_ratio = ar;
> +       else
> +               dp->dccps_options.dccpo_r_ack_ratio = ar;
> +
> +       return 0;
> +}
> +
>  static int dccp_feat_update_ccid(struct sock *sk, u8 type, u8 new_ccid_nr)
>  {
>         struct dccp_sock *dp = dccp_sk(sk);
> @@ -128,28 +156,58 @@ static int dccp_feat_update_ccid(struct
>         return 0;
>  }
>
> -/* XXX taking only u8 vals */
> -static int dccp_feat_update(struct sock *sk, u8 type, u8 feat, u8 val)
> +/* caller is responsible for sanity checks.  It is important that val is of 
> the
> + * right length and format
> + */
> +static int dccp_feat_update(struct sock *sk, u8 type, u8 feat, void *val)
>  {
> -       dccp_pr_debug("changing [%d] feat %d to %d\n", type, feat, val);
> +       dccp_pr_debug("changing [%d] feat %d\n", type, feat);
>
>         switch (feat) {
>         case DCCPF_CCID:
> -               return dccp_feat_update_ccid(sk, type, val);
> +               return dccp_feat_update_ccid(sk, type, *((u8*)val));
> +
> +       case DCCPF_ACK_RATIO:
> +               return dccp_feat_update_ar(sk, type, *((u16*)val));
> +
>         default:
> -               dccp_pr_debug("IMPLEMENT changing [%d] feat %d to %d\n",
> -                             type, feat, val);
> +               dccp_pr_debug("IMPLEMENT changing [%d] feat %d\n", type, 
> feat);
>                 break;
>         }
>         return 0;
>  }
>
> +static u8 *dccp_feat_find_intersect(u8 *spref, u8 slen, u8 *rpref, u8 rlen,
> +                                   u8 optlen)
> +{
> +       int i, j;
> +
> +       /* XXX lame algorithm here.  If values are in any order, we can be
> +        * smarter.  Also, we can provide specialized implementation for 1 
> byte
> +        * features, or features of particular types.
> +        */
> +       dccp_pr_debug("Searching for intersection slen %d rlen %d optlen 
> %d\n",
> +                     slen, rlen, optlen);
> +
> +       for (i = 0; i < slen; i+= optlen) {
> +               for (j = 0; j < rlen; j+= optlen) {
> +
> +                       if ((i + optlen) > slen || (j + optlen) > rlen)
> +                               return NULL;
> +
> +                       if (memcmp(&spref[i], &rpref[j], optlen) == 0)
> +                               return &spref[i];
> +               }
> +       }
> +       return NULL;
> +}
>  static int dccp_feat_reconcile(struct sock *sk, struct dccp_opt_pend *opt,
>                                u8 *rpref, u8 rlen)
>  {
>         struct dccp_sock *dp = dccp_sk(sk);
>         u8 *spref, slen, *res = NULL;
> -       int i, j, rc, agree = 1;
> +       int rc, agree = 1;
> +       int optlen = opt->dccpop_optlen;
>
>         BUG_ON(rpref == NULL);
>
> @@ -172,18 +230,7 @@ static int dccp_feat_reconcile(struct so
>
>         /* FIXME sanity check vals */
>
> -       /* Are values in any order?  XXX Lame "algorithm" here */
> -       /* XXX assume values are 1 byte */
> -       for (i = 0; i < slen; i++) {
> -               for (j = 0; j < rlen; j++) {
> -                       if (spref[i] == rpref[j]) {
> -                               res = &spref[i];
> -                               break;
> -                       }
> -               }
> -               if (res)
> -                       break;
> -       }
> +       res = dccp_feat_find_intersect(spref, slen, rpref, rlen, optlen);
>
>         /* we didn't agree on anything */
>         if (res == NULL) {
> @@ -207,14 +254,13 @@ static int dccp_feat_reconcile(struct so
>         }
>
>         /* need to put result and our preference list */
> -       /* XXX assume 1 byte vals */
> -       rlen = 1 + opt->dccpop_len;
> +       rlen = optlen + opt->dccpop_len;
>         rpref = kmalloc(rlen, GFP_ATOMIC);
>         if (rpref == NULL)
>                 return -ENOMEM;
>
> -       *rpref = *res;
> -       memcpy(&rpref[1], opt->dccpop_val, opt->dccpop_len);
> +       memcpy(rpref, res, optlen);
> +       memcpy(&rpref[optlen], opt->dccpop_val, opt->dccpop_len);
>
>         /* put it in the "confirm queue" */
>         if (opt->dccpop_sc == NULL) {
> @@ -235,7 +281,7 @@ static int dccp_feat_reconcile(struct so
>         opt->dccpop_sc->dccpoc_len = rlen;
>
>         /* update the option on our side [we are about to send the confirm] */
> -       rc = dccp_feat_update(sk, opt->dccpop_type, opt->dccpop_feat, *res);
> +       rc = dccp_feat_update(sk, opt->dccpop_type, opt->dccpop_feat, res);
>         if (rc) {
>                 kfree(opt->dccpop_sc->dccpoc_val);
>                 kfree(opt->dccpop_sc);
> @@ -329,7 +375,7 @@ static int dccp_feat_nn(struct sock *sk,
>         opt->dccpop_len  = len;
>
>         /* change feature */
> -       rc = dccp_feat_update(sk, type, feature, *val);
> +       rc = dccp_feat_update(sk, DCCPO_CHANGE_R, feature, val);
>         if (rc) {
>                 kfree(opt->dccpop_val);
>                 kfree(opt);
> @@ -462,7 +508,7 @@ int dccp_feat_confirm_recv(struct sock *
>
>                         /* We got a confirmation---change the option */
>                         dccp_feat_update(sk, opt->dccpop_type,
> -                                        opt->dccpop_feat, *val);
> +                                        opt->dccpop_feat, val);
>
>                         dccp_pr_debug("feat %d type %d confirmed %d\n",
>                                       feature, type, *val);
> @@ -584,10 +630,10 @@ out_clean:
>
>  EXPORT_SYMBOL_GPL(dccp_feat_clone);
>
> -static int __dccp_feat_init(struct sock *sk, u8 type, u8 feat, u8 *val, u8 
> len)
> +static int __dccp_feat_init(struct sock *sk, u8 type, u8 feat, void *val, u8 
> len)
>  {
>         int rc = -ENOMEM;
> -       u8 *copy = kmalloc(len, GFP_KERNEL);
> +       void *copy = kmalloc(len, GFP_KERNEL);
>
>         if (copy != NULL) {
>                 memcpy(copy, val, len);
> @@ -620,7 +666,7 @@ int dccp_feat_init(struct sock *sk)
>
>         /* Ack ratio */
>         rc = __dccp_feat_init(sk, DCCPO_CHANGE_L, DCCPF_ACK_RATIO,
> -                             &dp->dccps_options.dccpo_ack_ratio, 1);
> +                             &dp->dccps_options.dccpo_l_ack_ratio, 2);
>  out:
>         return rc;
>  }
> diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c
> index 266b6b2..305790d 100644
> --- a/net/dccp/ipv4.c
> +++ b/net/dccp/ipv4.c
> @@ -1095,7 +1095,6 @@ int dccp_v4_init_sock(struct sock *sk)
>         dp->dccps_mss_cache = 536;
>         dp->dccps_role = DCCP_ROLE_UNDEFINED;
>         dp->dccps_service = DCCP_SERVICE_INVALID_VALUE;
> -       dp->dccps_l_ack_ratio = dp->dccps_r_ack_ratio = 1;
>
>         return 0;
>  }
> diff --git a/net/dccp/options.c b/net/dccp/options.c
> index 7f99306..8852ffe 100644
> --- a/net/dccp/options.c
> +++ b/net/dccp/options.c
> @@ -28,7 +28,8 @@ static const struct dccp_options dccpo_d
>         .dccpo_sequence_window    = DCCPF_INITIAL_SEQUENCE_WINDOW,
>         .dccpo_rx_ccid            = DCCPF_INITIAL_CCID,
>         .dccpo_tx_ccid            = DCCPF_INITIAL_CCID,
> -       .dccpo_ack_ratio          = DCCPF_INITIAL_ACK_RATIO,
> +       .dccpo_l_ack_ratio        = DCCPF_INITIAL_ACK_RATIO,
> +       .dccpo_r_ack_ratio        = DCCPF_INITIAL_ACK_RATIO,
>         .dccpo_send_ack_vector    = DCCPF_INITIAL_SEND_ACK_VECTOR,
>         .dccpo_send_ndp_count     = DCCPF_INITIAL_SEND_NDP_COUNT,
>  };
> @@ -36,6 +37,8 @@ static const struct dccp_options dccpo_d
>  void dccp_options_init(struct dccp_options *dccpo)
>  {
>         memcpy(dccpo, &dccpo_default_values, sizeof(*dccpo));
> +       dccpo->dccpo_l_ack_ratio = htons(dccpo->dccpo_l_ack_ratio);
> +       dccpo->dccpo_r_ack_ratio = htons(dccpo->dccpo_r_ack_ratio);
>  }
>
>  static u32 dccp_decode_value_var(const unsigned char *bf, const u8 len)
>
-
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