]> bbs.cooldavid.org Git - net-next-2.6.git/commitdiff
Merge branch 'dccp' of git://eden-feed.erg.abdn.ac.uk/net-next-2.6
authorDavid S. Miller <davem@davemloft.net>
Thu, 16 Sep 2010 03:21:48 +0000 (20:21 -0700)
committerDavid S. Miller <davem@davemloft.net>
Thu, 16 Sep 2010 03:21:48 +0000 (20:21 -0700)
net/dccp/ccids/ccid3.c
net/dccp/ccids/ccid3.h
net/dccp/ccids/lib/packet_history.c
net/dccp/ccids/lib/packet_history.h

index 278e170693229c7d0cc2af20ad6f6f1e8d9fe56c..ce80591300707c86b91a213922b6b392973b3c40 100644 (file)
@@ -91,19 +91,16 @@ static inline u64 rfc3390_initial_rate(struct sock *sk)
        return scaled_div(w_init << 6, hc->tx_rtt);
 }
 
-/*
- * Recalculate t_ipi and delta (should be called whenever X changes)
+/**
+ * ccid3_update_send_interval  -  Calculate new t_ipi = s / X_inst
+ * This respects the granularity of X_inst (64 * bytes/second).
  */
 static void ccid3_update_send_interval(struct ccid3_hc_tx_sock *hc)
 {
-       /* Calculate new t_ipi = s / X_inst (X_inst is in 64 * bytes/second) */
        hc->tx_t_ipi = scaled_div32(((u64)hc->tx_s) << 6, hc->tx_x);
 
-       /* Calculate new delta by delta = min(t_ipi / 2, t_gran / 2) */
-       hc->tx_delta = min_t(u32, hc->tx_t_ipi / 2, TFRC_OPSYS_HALF_TIME_GRAN);
-
-       ccid3_pr_debug("t_ipi=%u, delta=%u, s=%u, X=%u\n", hc->tx_t_ipi,
-                      hc->tx_delta, hc->tx_s, (unsigned)(hc->tx_x >> 6));
+       ccid3_pr_debug("t_ipi=%u, s=%u, X=%u\n", hc->tx_t_ipi,
+                      hc->tx_s, (unsigned)(hc->tx_x >> 6));
 }
 
 static u32 ccid3_hc_tx_idle_rtt(struct ccid3_hc_tx_sock *hc, ktime_t now)
@@ -332,15 +329,15 @@ static int ccid3_hc_tx_send_packet(struct sock *sk, struct sk_buff *skb)
                delay = ktime_us_delta(hc->tx_t_nom, now);
                ccid3_pr_debug("delay=%ld\n", (long)delay);
                /*
-                *      Scheduling of packet transmissions [RFC 3448, 4.6]
+                *      Scheduling of packet transmissions (RFC 5348, 8.3)
                 *
                 * if (t_now > t_nom - delta)
                 *       // send the packet now
                 * else
                 *       // send the packet in (t_nom - t_now) milliseconds.
                 */
-               if (delay - (s64)hc->tx_delta >= 1000)
-                       return (u32)delay / 1000L;
+               if (delay >= TFRC_T_DELTA)
+                       return (u32)delay / USEC_PER_MSEC;
 
                ccid3_hc_tx_update_win_count(hc, now);
                break;
@@ -373,6 +370,7 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
 {
        struct ccid3_hc_tx_sock *hc = ccid3_hc_tx_sk(sk);
        struct ccid3_options_received *opt_recv = &hc->tx_options_received;
+       struct tfrc_tx_hist_entry *acked;
        ktime_t now;
        unsigned long t_nfb;
        u32 pinv, r_sample;
@@ -386,17 +384,24 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
            hc->tx_state != TFRC_SSTATE_NO_FBACK)
                return;
 
-       now = ktime_get_real();
-
-       /* Estimate RTT from history if ACK number is valid */
-       r_sample = tfrc_tx_hist_rtt(hc->tx_hist,
-                                   DCCP_SKB_CB(skb)->dccpd_ack_seq, now);
-       if (r_sample == 0) {
-               DCCP_WARN("%s(%p): %s with bogus ACK-%llu\n", dccp_role(sk), sk,
-                         dccp_packet_name(DCCP_SKB_CB(skb)->dccpd_type),
-                         (unsigned long long)DCCP_SKB_CB(skb)->dccpd_ack_seq);
+       /*
+        * Locate the acknowledged packet in the TX history.
+        *
+        * Returning "entry not found" here can for instance happen when
+        *  - the host has not sent out anything (e.g. a passive server),
+        *  - the Ack is outdated (packet with higher Ack number was received),
+        *  - it is a bogus Ack (for a packet not sent on this connection).
+        */
+       acked = tfrc_tx_hist_find_entry(hc->tx_hist, dccp_hdr_ack_seq(skb));
+       if (acked == NULL)
                return;
-       }
+       /* For the sake of RTT sampling, ignore/remove all older entries */
+       tfrc_tx_hist_purge(&acked->next);
+
+       /* Update the moving average for the RTT estimate (RFC 3448, 4.3) */
+       now       = ktime_get_real();
+       r_sample  = dccp_sample_rtt(sk, ktime_us_delta(now, acked->stamp));
+       hc->tx_rtt = tfrc_ewma(hc->tx_rtt, r_sample, 9);
 
        /* Update receive rate in units of 64 * bytes/second */
        hc->tx_x_recv = opt_recv->ccid3or_receive_rate;
@@ -408,11 +413,7 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
                hc->tx_p = 0;
        else                                   /* can not exceed 100% */
                hc->tx_p = scaled_div(1, pinv);
-       /*
-        * Validate new RTT sample and update moving average
-        */
-       r_sample = dccp_sample_rtt(sk, r_sample);
-       hc->tx_rtt = tfrc_ewma(hc->tx_rtt, r_sample, 9);
+
        /*
         * Update allowed sending rate X as per draft rfc3448bis-00, 4.2/3
         */
@@ -484,60 +485,31 @@ static int ccid3_hc_tx_parse_options(struct sock *sk, unsigned char option,
                                     unsigned char len, u16 idx,
                                     unsigned char *value)
 {
-       int rc = 0;
-       const struct dccp_sock *dp = dccp_sk(sk);
        struct ccid3_hc_tx_sock *hc = ccid3_hc_tx_sk(sk);
        struct ccid3_options_received *opt_recv = &hc->tx_options_received;
        __be32 opt_val;
 
-       if (opt_recv->ccid3or_seqno != dp->dccps_gsr) {
-               opt_recv->ccid3or_seqno              = dp->dccps_gsr;
-               opt_recv->ccid3or_loss_event_rate    = ~0;
-               opt_recv->ccid3or_loss_intervals_idx = 0;
-               opt_recv->ccid3or_loss_intervals_len = 0;
-               opt_recv->ccid3or_receive_rate       = 0;
-       }
-
        switch (option) {
+       case TFRC_OPT_RECEIVE_RATE:
        case TFRC_OPT_LOSS_EVENT_RATE:
                if (unlikely(len != 4)) {
-                       DCCP_WARN("%s(%p), invalid len %d "
-                                 "for TFRC_OPT_LOSS_EVENT_RATE\n",
-                                 dccp_role(sk), sk, len);
-                       rc = -EINVAL;
-               } else {
-                       opt_val = get_unaligned((__be32 *)value);
-                       opt_recv->ccid3or_loss_event_rate = ntohl(opt_val);
-                       ccid3_pr_debug("%s(%p), LOSS_EVENT_RATE=%u\n",
-                                      dccp_role(sk), sk,
-                                      opt_recv->ccid3or_loss_event_rate);
+                       DCCP_WARN("%s(%p), invalid len %d for %u\n",
+                                 dccp_role(sk), sk, len, option);
+                       return -EINVAL;
                }
-               break;
-       case TFRC_OPT_LOSS_INTERVALS:
-               opt_recv->ccid3or_loss_intervals_idx = idx;
-               opt_recv->ccid3or_loss_intervals_len = len;
-               ccid3_pr_debug("%s(%p), LOSS_INTERVALS=(%u, %u)\n",
-                              dccp_role(sk), sk,
-                              opt_recv->ccid3or_loss_intervals_idx,
-                              opt_recv->ccid3or_loss_intervals_len);
-               break;
-       case TFRC_OPT_RECEIVE_RATE:
-               if (unlikely(len != 4)) {
-                       DCCP_WARN("%s(%p), invalid len %d "
-                                 "for TFRC_OPT_RECEIVE_RATE\n",
-                                 dccp_role(sk), sk, len);
-                       rc = -EINVAL;
-               } else {
-                       opt_val = get_unaligned((__be32 *)value);
-                       opt_recv->ccid3or_receive_rate = ntohl(opt_val);
+               opt_val = ntohl(get_unaligned((__be32 *)value));
+
+               if (option == TFRC_OPT_RECEIVE_RATE) {
+                       opt_recv->ccid3or_receive_rate = opt_val;
                        ccid3_pr_debug("%s(%p), RECEIVE_RATE=%u\n",
-                                      dccp_role(sk), sk,
-                                      opt_recv->ccid3or_receive_rate);
+                                      dccp_role(sk), sk, opt_val);
+               } else {
+                       opt_recv->ccid3or_loss_event_rate = opt_val;
+                       ccid3_pr_debug("%s(%p), LOSS_EVENT_RATE=%u\n",
+                                      dccp_role(sk), sk, opt_val);
                }
-               break;
        }
-
-       return rc;
+       return 0;
 }
 
 static int ccid3_hc_tx_init(struct ccid *ccid, struct sock *sk)
index b7e569c22f3658f4c9366982902d05a43236a907..9eb90b863abd5ae10e1105d15f302016a8366ff0 100644 (file)
 /* Two seconds as per RFC 5348, 4.2 */
 #define TFRC_INITIAL_TIMEOUT      (2 * USEC_PER_SEC)
 
-/* In usecs - half the scheduling granularity as per RFC3448 4.6 */
-#define TFRC_OPSYS_HALF_TIME_GRAN  (USEC_PER_SEC / (2 * HZ))
-
 /* Parameter t_mbi from [RFC 3448, 4.3]: backoff interval in seconds */
 #define TFRC_T_MBI                64
 
+/*
+ * The t_delta parameter (RFC 5348, 8.3): delays of less than %USEC_PER_MSEC are
+ * rounded down to 0, since sk_reset_timer() here uses millisecond granularity.
+ * Hence we can use a constant t_delta = %USEC_PER_MSEC when HZ >= 500. A coarse
+ * resolution of HZ < 500 means that the error is below one timer tick (t_gran)
+ * when using the constant t_delta  =  t_gran / 2  =  %USEC_PER_SEC / (2 * HZ).
+ */
+#if (HZ >= 500)
+# define TFRC_T_DELTA             USEC_PER_MSEC
+#else
+# define TFRC_T_DELTA             (USEC_PER_SEC / (2 * HZ))
+#endif
+
 enum ccid3_options {
        TFRC_OPT_LOSS_EVENT_RATE = 192,
        TFRC_OPT_LOSS_INTERVALS  = 193,
@@ -58,9 +68,6 @@ enum ccid3_options {
 };
 
 struct ccid3_options_received {
-       u64 ccid3or_seqno:48,
-           ccid3or_loss_intervals_idx:16;
-       u16 ccid3or_loss_intervals_len;
        u32 ccid3or_loss_event_rate;
        u32 ccid3or_receive_rate;
 };
@@ -90,7 +97,6 @@ enum ccid3_hc_tx_states {
  * @tx_no_feedback_timer: Handle to no feedback timer
  * @tx_t_ld:             Time last doubled during slow start
  * @tx_t_nom:            Nominal send time of next packet
- * @tx_delta:            Send timer delta (RFC 3448, 4.6) in usecs
  * @tx_hist:             Packet history
  * @tx_options_received:  Parsed set of retrieved options
  */
@@ -109,7 +115,6 @@ struct ccid3_hc_tx_sock {
        struct timer_list               tx_no_feedback_timer;
        ktime_t                         tx_t_ld;
        ktime_t                         tx_t_nom;
-       u32                             tx_delta;
        struct tfrc_tx_hist_entry       *tx_hist;
        struct ccid3_options_received   tx_options_received;
 };
index 3a4f414e94a0051bf66429739680d3d5ee8fb432..de8fe294bf0bccfce4d865ea15590162e1225e06 100644 (file)
 #include "packet_history.h"
 #include "../../dccp.h"
 
-/**
- *  tfrc_tx_hist_entry  -  Simple singly-linked TX history list
- *  @next:  next oldest entry (LIFO order)
- *  @seqno: sequence number of this entry
- *  @stamp: send time of packet with sequence number @seqno
- */
-struct tfrc_tx_hist_entry {
-       struct tfrc_tx_hist_entry *next;
-       u64                       seqno;
-       ktime_t                   stamp;
-};
-
 /*
  * Transmitter History Routines
  */
@@ -71,15 +59,6 @@ void tfrc_tx_packet_history_exit(void)
        }
 }
 
-static struct tfrc_tx_hist_entry *
-       tfrc_tx_hist_find_entry(struct tfrc_tx_hist_entry *head, u64 seqno)
-{
-       while (head != NULL && head->seqno != seqno)
-               head = head->next;
-
-       return head;
-}
-
 int tfrc_tx_hist_add(struct tfrc_tx_hist_entry **headp, u64 seqno)
 {
        struct tfrc_tx_hist_entry *entry = kmem_cache_alloc(tfrc_tx_hist_slab, gfp_any());
@@ -107,24 +86,6 @@ void tfrc_tx_hist_purge(struct tfrc_tx_hist_entry **headp)
        *headp = NULL;
 }
 
-u32 tfrc_tx_hist_rtt(struct tfrc_tx_hist_entry *head, const u64 seqno,
-                    const ktime_t now)
-{
-       u32 rtt = 0;
-       struct tfrc_tx_hist_entry *packet = tfrc_tx_hist_find_entry(head, seqno);
-
-       if (packet != NULL) {
-               rtt = ktime_us_delta(now, packet->stamp);
-               /*
-                * Garbage-collect older (irrelevant) entries:
-                */
-               tfrc_tx_hist_purge(&packet->next);
-       }
-
-       return rtt;
-}
-
-
 /*
  *     Receiver History Routines
  */
index 7df6c52999999a4c76c99802d0dbcf54a8654211..7ee4a9d9d3352337bb5e899d214a754b740ac8c0 100644 (file)
 #include <linux/slab.h>
 #include "tfrc.h"
 
-struct tfrc_tx_hist_entry;
+/**
+ *  tfrc_tx_hist_entry  -  Simple singly-linked TX history list
+ *  @next:  next oldest entry (LIFO order)
+ *  @seqno: sequence number of this entry
+ *  @stamp: send time of packet with sequence number @seqno
+ */
+struct tfrc_tx_hist_entry {
+       struct tfrc_tx_hist_entry *next;
+       u64                       seqno;
+       ktime_t                   stamp;
+};
+
+static inline struct tfrc_tx_hist_entry *
+       tfrc_tx_hist_find_entry(struct tfrc_tx_hist_entry *head, u64 seqno)
+{
+       while (head != NULL && head->seqno != seqno)
+               head = head->next;
+       return head;
+}
 
 extern int  tfrc_tx_hist_add(struct tfrc_tx_hist_entry **headp, u64 seqno);
 extern void tfrc_tx_hist_purge(struct tfrc_tx_hist_entry **headp);
-extern u32  tfrc_tx_hist_rtt(struct tfrc_tx_hist_entry *head,
-                            const u64 seqno, const ktime_t now);
 
 /* Subtraction a-b modulo-16, respects circular wrap-around */
 #define SUB16(a, b) (((a) + 16 - (b)) & 0xF)