[NET]: use __read_mostly on kmem_cache_t , DEFINE_SNMP_STAT pointers
[deliverable/linux.git] / net / dccp / ccids / ccid3.c
index 4f45902cb55e23dc954f003c12d476a9ae8b27bd..cf93b019ecbe719d13c4bdaadd30a0431342a90c 100644 (file)
@@ -2,12 +2,12 @@
  *  net/dccp/ccids/ccid3.c
  *
  *  Copyright (c) 2005 The University of Waikato, Hamilton, New Zealand.
+ *  Copyright (c) 2005 Ian McDonald <iam4@cs.waikato.ac.nz>
  *
  *  An implementation of the DCCP protocol
  *
  *  This code has been developed by the University of Waikato WAND
  *  research group. For further information please see http://www.wand.net.nz/
- *  or e-mail Ian McDonald - iam4@cs.waikato.ac.nz
  *
  *  This code also uses code from Lulea University, rereleased as GPL by its
  *  authors:
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+#include <linux/config.h>
 #include "../ccid.h"
 #include "../dccp.h"
+#include "../packet_history.h"
 #include "ccid3.h"
 
 #ifdef CCID3_DEBUG
@@ -53,12 +55,10 @@ extern int ccid3_debug;
 #define TFRC_STD_PACKET_SIZE     256
 #define TFRC_MAX_PACKET_SIZE   65535
 
-#define USEC_IN_SEC                1000000
-
-#define TFRC_INITIAL_TIMEOUT      (2 * USEC_IN_SEC)
+#define TFRC_INITIAL_TIMEOUT      (2 * USEC_PER_SEC)
 /* two seconds as per CCID3 spec 11 */
 
-#define TFRC_OPSYS_HALF_TIME_GRAN      (USEC_IN_SEC / (2 * HZ))
+#define TFRC_OPSYS_HALF_TIME_GRAN      (USEC_PER_SEC / (2 * HZ))
 /* above is in usecs - half the scheduling granularity as per RFC3448 4.6 */
 
 #define TFRC_WIN_COUNT_PER_RTT     4
@@ -82,62 +82,13 @@ enum ccid3_options {
 
 static int ccid3_debug;
 
-static kmem_cache_t *ccid3_tx_hist_slab;
-static kmem_cache_t *ccid3_rx_hist_slab;
-static kmem_cache_t *ccid3_loss_interval_hist_slab;
-
-static inline struct ccid3_tx_hist_entry *ccid3_tx_hist_entry_new(int prio)
-{
-       struct ccid3_tx_hist_entry *entry = kmem_cache_alloc(ccid3_tx_hist_slab, prio);
-
-       if (entry != NULL)
-               entry->ccid3htx_sent = 0;
-
-       return entry;
-}
+static struct dccp_tx_hist *ccid3_tx_hist;
+static struct dccp_rx_hist *ccid3_rx_hist;
 
-static inline void ccid3_tx_hist_entry_delete(struct ccid3_tx_hist_entry *entry)
-{
-       if (entry != NULL)
-               kmem_cache_free(ccid3_tx_hist_slab, entry);
-}
+static kmem_cache_t *ccid3_loss_interval_hist_slab __read_mostly;
 
-static inline struct ccid3_rx_hist_entry *ccid3_rx_hist_entry_new(struct sock *sk,
-                                                                 struct sk_buff *skb,
-                                                                 int prio)
-{
-       struct ccid3_rx_hist_entry *entry = kmem_cache_alloc(ccid3_rx_hist_slab, prio);
-
-       if (entry != NULL) {
-               const struct dccp_hdr *dh = dccp_hdr(skb);
-
-               entry->ccid3hrx_seqno     = DCCP_SKB_CB(skb)->dccpd_seq;
-               entry->ccid3hrx_win_count = dh->dccph_ccval;
-               entry->ccid3hrx_type      = dh->dccph_type;
-               entry->ccid3hrx_ndp       = dccp_sk(sk)->dccps_options_received.dccpor_ndp;
-               do_gettimeofday(&(entry->ccid3hrx_tstamp));
-       }
-
-       return entry;
-}
-
-static inline void ccid3_rx_hist_entry_delete(struct ccid3_rx_hist_entry *entry)
-{
-       if (entry != NULL)
-               kmem_cache_free(ccid3_rx_hist_slab, entry);
-}
-
-static void ccid3_rx_history_delete(struct list_head *hist)
-{
-       struct ccid3_rx_hist_entry *entry, *next;
-
-       list_for_each_entry_safe(entry, next, hist, ccid3hrx_node) {
-               list_del_init(&entry->ccid3hrx_node);
-               kmem_cache_free(ccid3_rx_hist_slab, entry);
-       }
-}
-
-static inline struct ccid3_loss_interval_hist_entry *ccid3_loss_interval_hist_entry_new(int prio)
+static inline struct ccid3_loss_interval_hist_entry *
+       ccid3_loss_interval_hist_entry_new(const unsigned int __nocast prio)
 {
        return kmem_cache_alloc(ccid3_loss_interval_hist_slab, prio);
 }
@@ -203,31 +154,26 @@ static inline void ccid3_hc_tx_set_state(struct sock *sk, enum ccid3_hc_tx_state
        hctx->ccid3hctx_state = state;
 }
 
-static void timeval_sub(struct timeval large, struct timeval small, struct timeval *result) {
-
+static void timeval_sub(struct timeval large, struct timeval small,
+                       struct timeval *result)
+{
        result->tv_sec = large.tv_sec-small.tv_sec;
        if (large.tv_usec < small.tv_usec) {
                (result->tv_sec)--;
-               result->tv_usec = USEC_IN_SEC+large.tv_usec-small.tv_usec;
+               result->tv_usec = USEC_PER_SEC +
+                                 large.tv_usec - small.tv_usec;
        } else
                result->tv_usec = large.tv_usec-small.tv_usec;
 }
 
-static inline void timeval_fix(struct timeval *tv) {
-       if (tv->tv_usec >= USEC_IN_SEC) {
+static inline void timeval_fix(struct timeval *tv)
+{
+       if (tv->tv_usec >= USEC_PER_SEC) {
                tv->tv_sec++;
-               tv->tv_usec -= USEC_IN_SEC;
+               tv->tv_usec -= USEC_PER_SEC;
        }
 }
 
-/* returns the difference in usecs between timeval passed in and current time */
-static inline u32 now_delta(struct timeval tv) {
-       struct timeval now;
-       
-       do_gettimeofday(&now);
-       return ((now.tv_sec-tv.tv_sec)*1000000+now.tv_usec-tv.tv_usec);
-}
-
 #define CALCX_ARRSIZE 500
 
 #define CALCX_SPLIT 50000
@@ -959,7 +905,7 @@ static void ccid3_hc_tx_no_feedback_timer(unsigned long data)
                        hctx->ccid3hctx_x = 10;
                }
                /* Schedule no feedback timer to expire in max(4 * R, 2 * s / X) */
-               next_tmout = max_t(u32, inet_csk(sk)->icsk_rto, 
+               next_tmout = max_t(u32, hctx->ccid3hctx_t_rto, 
                                   2 * (hctx->ccid3hctx_s * 100000) / (hctx->ccid3hctx_x / 10));
                break;
        default:
@@ -977,13 +923,14 @@ out:
        sock_put(sk);
 }
 
-static int ccid3_hc_tx_send_packet(struct sock *sk, struct sk_buff *skb,
-                                  int len, long *delay)
+static int ccid3_hc_tx_send_packet(struct sock *sk,
+                                  struct sk_buff *skb, int len)
 {
        struct dccp_sock *dp = dccp_sk(sk);
        struct ccid3_hc_tx_sock *hctx = dp->dccps_hc_tx_ccid_private;
-       struct ccid3_tx_hist_entry *new_packet = NULL;
+       struct dccp_tx_hist_entry *new_packet;
        struct timeval now;
+       long delay;
        int rc = -ENOTCONN;
 
 //     ccid3_pr_debug("%s, sk=%p, skb=%p, len=%d\n", dccp_role(sk), sk, skb, len);
@@ -996,12 +943,9 @@ static int ccid3_hc_tx_send_packet(struct sock *sk, struct sk_buff *skb,
                goto out;
 
        /* See if last packet allocated was not sent */
-       if (!list_empty(&hctx->ccid3hctx_hist))
-               new_packet = list_entry(hctx->ccid3hctx_hist.next,
-                                       struct ccid3_tx_hist_entry, ccid3htx_node);
-
-       if (new_packet == NULL || new_packet->ccid3htx_sent) {
-               new_packet = ccid3_tx_hist_entry_new(SLAB_ATOMIC);
+       new_packet = dccp_tx_hist_head(&hctx->ccid3hctx_hist);
+       if (new_packet == NULL || new_packet->dccphtx_sent) {
+               new_packet = dccp_tx_hist_entry_new(ccid3_tx_hist, SLAB_ATOMIC);
 
                rc = -ENOBUFS;
                if (new_packet == NULL) {
@@ -1010,7 +954,7 @@ static int ccid3_hc_tx_send_packet(struct sock *sk, struct sk_buff *skb,
                        goto out;
                }
 
-               list_add(&new_packet->ccid3htx_node, &hctx->ccid3hctx_hist);
+               dccp_tx_hist_add_entry(&hctx->ccid3hctx_hist, new_packet);
        }
 
        do_gettimeofday(&now);
@@ -1037,11 +981,11 @@ static int ccid3_hc_tx_send_packet(struct sock *sk, struct sk_buff *skb,
                break;
        case TFRC_SSTATE_NO_FBACK:
        case TFRC_SSTATE_FBACK:
-               *delay = (now_delta(hctx->ccid3hctx_t_nom) - hctx->ccid3hctx_delta);
-               ccid3_pr_debug("send_packet delay=%ld\n",*delay);
-               *delay /= -1000;
+               delay = (now_delta(hctx->ccid3hctx_t_nom) - hctx->ccid3hctx_delta);
+               ccid3_pr_debug("send_packet delay=%ld\n", delay);
+               delay /= -1000;
                /* divide by -1000 is to convert to ms and get sign right */
-               rc = *delay > 0 ? -EAGAIN : 0;
+               rc = delay > 0 ? -EAGAIN : 0;
                break;
        default:
                printk(KERN_CRIT "%s: %s, sk=%p, Illegal state (%d)!\n",
@@ -1053,7 +997,9 @@ static int ccid3_hc_tx_send_packet(struct sock *sk, struct sk_buff *skb,
 
        /* Can we send? if so add options and add to packet history */
        if (rc == 0)
-               new_packet->ccid3htx_win_count = DCCP_SKB_CB(skb)->dccpd_ccval = hctx->ccid3hctx_last_win_count;
+               new_packet->dccphtx_ccval =
+                       DCCP_SKB_CB(skb)->dccpd_ccval =
+                               hctx->ccid3hctx_last_win_count;
 out:
        return rc;
 }
@@ -1062,10 +1008,8 @@ static void ccid3_hc_tx_packet_sent(struct sock *sk, int more, int len)
 {
        struct dccp_sock *dp = dccp_sk(sk);
        struct ccid3_hc_tx_sock *hctx = dp->dccps_hc_tx_ccid_private;
-       struct ccid3_tx_hist_entry *packet = NULL;
        struct timeval now;
 
-//     ccid3_pr_debug("%s, sk=%p, more=%d, len=%d\n", dccp_role(sk), sk, more, len);
        BUG_ON(hctx == NULL);
 
        if (hctx->ccid3hctx_state == TFRC_SSTATE_TERM) {
@@ -1079,20 +1023,23 @@ static void ccid3_hc_tx_packet_sent(struct sock *sk, int more, int len)
        /* check if we have sent a data packet */
        if (len > 0) {
                unsigned long quarter_rtt;
+               struct dccp_tx_hist_entry *packet;
 
-               if (list_empty(&hctx->ccid3hctx_hist)) {
+               packet = dccp_tx_hist_head(&hctx->ccid3hctx_hist);
+               if (packet == NULL) {
                        printk(KERN_CRIT "%s: packet doesn't exists in history!\n", __FUNCTION__);
                        return;
                }
-               packet = list_entry(hctx->ccid3hctx_hist.next, struct ccid3_tx_hist_entry, ccid3htx_node);
-               if (packet->ccid3htx_sent) {
+               if (packet->dccphtx_sent) {
                        printk(KERN_CRIT "%s: no unsent packet in history!\n", __FUNCTION__);
                        return;
                }
-               packet->ccid3htx_tstamp = now;
-               packet->ccid3htx_seqno  = dp->dccps_gss;
-               // ccid3_pr_debug("%s, sk=%p, seqno=%llu inserted!\n", dccp_role(sk), sk, packet->ccid3htx_seqno);
-
+               packet->dccphtx_tstamp = now;
+               packet->dccphtx_seqno  = dp->dccps_gss;
+#if 0
+               ccid3_pr_debug("%s, sk=%p, seqno=%llu inserted!\n",
+                              dccp_role(sk), sk, packet->dccphtx_seqno);
+#endif
                /*
                 * Check if win_count have changed */
                /* COMPLIANCE_BEGIN
@@ -1105,18 +1052,19 @@ static void ccid3_hc_tx_packet_sent(struct sock *sk, int more, int len)
                                                            min_t(unsigned long, quarter_rtt, 5)) % 16;
                        ccid3_pr_debug("%s, sk=%p, window changed from %u to %u!\n",
                                       dccp_role(sk), sk,
-                                      packet->ccid3htx_win_count,
+                                      packet->dccphtx_ccval,
                                       hctx->ccid3hctx_last_win_count);
                }
                /* COMPLIANCE_END */
 #if 0
                ccid3_pr_debug("%s, sk=%p, packet sent (%llu,%u)\n",
                               dccp_role(sk), sk,
-                              packet->ccid3htx_seqno,
-                              packet->ccid3htx_win_count);
+                              packet->dccphtx_seqno,
+                              packet->dccphtx_ccval);
 #endif
                hctx->ccid3hctx_idle = 0;
-               packet->ccid3htx_sent = 1;
+               packet->dccphtx_rtt  = hctx->ccid3hctx_rtt;
+               packet->dccphtx_sent = 1;
        } else
                ccid3_pr_debug("%s, sk=%p, seqno=%llu NOT inserted!\n",
                               dccp_role(sk), sk, dp->dccps_gss);
@@ -1151,9 +1099,9 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
        struct dccp_sock *dp = dccp_sk(sk);
        struct ccid3_hc_tx_sock *hctx = dp->dccps_hc_tx_ccid_private;
        struct ccid3_options_received *opt_recv;
-       struct ccid3_tx_hist_entry *entry, *next, *packet;
+       struct dccp_tx_hist_entry *packet;
        unsigned long next_tmout; 
-       u16 t_elapsed;
+       u32 t_elapsed;
        u32 pinv;
        u32 x_recv;
        u32 r_sample;
@@ -1190,13 +1138,8 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
                /* Calculate new round trip sample by
                 * R_sample = (now - t_recvdata) - t_delay */
                /* get t_recvdata from history */
-               packet = NULL;
-               list_for_each_entry_safe(entry, next, &hctx->ccid3hctx_hist, ccid3htx_node)
-                       if (entry->ccid3htx_seqno == DCCP_SKB_CB(skb)->dccpd_ack_seq) {
-                               packet = entry;
-                               break;
-                       }
-
+               packet = dccp_tx_hist_find_entry(&hctx->ccid3hctx_hist,
+                                                DCCP_SKB_CB(skb)->dccpd_ack_seq);
                if (packet == NULL) {
                        ccid3_pr_debug("%s, sk=%p, seqno %llu(%s) does't exist in history!\n",
                                       dccp_role(sk), sk, DCCP_SKB_CB(skb)->dccpd_ack_seq,
@@ -1205,7 +1148,7 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
                }
 
                /* Update RTT */
-               r_sample = now_delta(packet->ccid3htx_tstamp);
+               r_sample = now_delta(packet->dccphtx_tstamp);
                /* FIXME: */
                // r_sample -= usecs_to_jiffies(t_elapsed * 10);
 
@@ -1236,7 +1179,8 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
                               r_sample);
 
                /* Update timeout interval */
-               inet_csk(sk)->icsk_rto = max_t(u32, 4 * hctx->ccid3hctx_rtt, USEC_IN_SEC);
+               hctx->ccid3hctx_t_rto = max_t(u32, 4 * hctx->ccid3hctx_rtt,
+                                             USEC_PER_SEC);
 
                /* Update receive rate */
                hctx->ccid3hctx_x_recv = x_recv;   /* x_recv in bytes per second */
@@ -1261,7 +1205,7 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
 
                /* Update next send time */
                if (hctx->ccid3hctx_t_ipi > (hctx->ccid3hctx_t_nom).tv_usec) {
-                       (hctx->ccid3hctx_t_nom).tv_usec += USEC_IN_SEC;
+                       hctx->ccid3hctx_t_nom.tv_usec += USEC_PER_SEC;
                        (hctx->ccid3hctx_t_nom).tv_sec--;
                }
                /* FIXME - if no feedback then t_ipi can go > 1 second */
@@ -1272,13 +1216,9 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
                ccid3_calc_new_delta(hctx);
 
                /* remove all packets older than the one acked from history */
-#if 0
-               FIXME!
-               list_for_each_entry_safe_continue(entry, next, &hctx->ccid3hctx_hist, ccid3htx_node) {
-                       list_del_init(&entry->ccid3htx_node);
-                       ccid3_tx_hist_entry_delete(entry);
-               }
-#endif
+               dccp_tx_hist_purge_older(ccid3_tx_hist,
+                                        &hctx->ccid3hctx_hist, packet);
+
                if (hctx->ccid3hctx_x < 10) {
                        ccid3_pr_debug("ccid3_hc_tx_packet_recv hctx->ccid3hctx_x < 10\n");
                        hctx->ccid3hctx_x = 10;
@@ -1286,8 +1226,9 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
                /* to prevent divide by zero below */
 
                /* Schedule no feedback timer to expire in max(4 * R, 2 * s / X) */
-               next_tmout = max(inet_csk(sk)->icsk_rto,
-                       2 * (hctx->ccid3hctx_s * 100000) / (hctx->ccid3hctx_x/10));
+               next_tmout = max(hctx->ccid3hctx_t_rto,
+                                (2 * (hctx->ccid3hctx_s * 100000) /
+                                 (hctx->ccid3hctx_x / 10)));
                /* maths with 100000 and 10 is to prevent overflow with 32 bit */
 
                ccid3_pr_debug("%s, sk=%p, Scheduled no feedback timer to expire in %lu jiffies (%luus)\n",
@@ -1398,7 +1339,7 @@ static int ccid3_hc_tx_init(struct sock *sk)
 
        hctx->ccid3hctx_x     = hctx->ccid3hctx_s; /* set transmission rate to 1 packet per second */
        hctx->ccid3hctx_rtt   = 4; /* See ccid3_hc_tx_packet_sent win_count calculatation */
-       inet_csk(sk)->icsk_rto = USEC_IN_SEC;
+       hctx->ccid3hctx_t_rto = USEC_PER_SEC;
        hctx->ccid3hctx_state = TFRC_SSTATE_NO_SENT;
        INIT_LIST_HEAD(&hctx->ccid3hctx_hist);
        init_timer(&hctx->ccid3hctx_no_feedback_timer);
@@ -1410,7 +1351,6 @@ static void ccid3_hc_tx_exit(struct sock *sk)
 {
        struct dccp_sock *dp = dccp_sk(sk);
        struct ccid3_hc_tx_sock *hctx = dp->dccps_hc_tx_ccid_private;
-       struct ccid3_tx_hist_entry *entry, *next;
 
        ccid3_pr_debug("%s, sk=%p\n", dccp_role(sk), sk);
        BUG_ON(hctx == NULL);
@@ -1419,10 +1359,7 @@ static void ccid3_hc_tx_exit(struct sock *sk)
        sk_stop_timer(sk, &hctx->ccid3hctx_no_feedback_timer);
 
        /* Empty packet history */
-       list_for_each_entry_safe(entry, next, &hctx->ccid3hctx_hist, ccid3htx_node) {
-               list_del_init(&entry->ccid3htx_node);
-               ccid3_tx_hist_entry_delete(entry);
-       }
+       dccp_tx_hist_purge(ccid3_tx_hist, &hctx->ccid3hctx_hist);
 
        kfree(dp->dccps_hc_tx_ccid_private);
        dp->dccps_hc_tx_ccid_private = NULL;
@@ -1464,39 +1401,40 @@ static inline void ccid3_hc_rx_set_state(struct sock *sk, enum ccid3_hc_rx_state
        hcrx->ccid3hcrx_state = state;
 }
 
-static int ccid3_hc_rx_add_hist(struct sock *sk, struct ccid3_rx_hist_entry *packet)
+static int ccid3_hc_rx_add_hist(struct sock *sk,
+                               struct dccp_rx_hist_entry *packet)
 {
        struct dccp_sock *dp = dccp_sk(sk);
        struct ccid3_hc_rx_sock *hcrx = dp->dccps_hc_rx_ccid_private;
-       struct ccid3_rx_hist_entry *entry, *next;
+       struct dccp_rx_hist_entry *entry, *next, *iter;
        u8 num_later = 0;
 
-       if (list_empty(&hcrx->ccid3hcrx_hist))
-               list_add(&packet->ccid3hrx_node, &hcrx->ccid3hcrx_hist);
+       iter = dccp_rx_hist_head(&hcrx->ccid3hcrx_hist);
+       if (iter == NULL)
+               dccp_rx_hist_add_entry(&hcrx->ccid3hcrx_hist, packet);
        else {
-               u64 seqno = packet->ccid3hrx_seqno;
-               struct ccid3_rx_hist_entry *iter = list_entry(hcrx->ccid3hcrx_hist.next,
-                                                             struct ccid3_rx_hist_entry,
-                                                             ccid3hrx_node);
-               if (after48(seqno, iter->ccid3hrx_seqno))
-                       list_add(&packet->ccid3hrx_node, &hcrx->ccid3hcrx_hist);
+               const u64 seqno = packet->dccphrx_seqno;
+
+               if (after48(seqno, iter->dccphrx_seqno))
+                       dccp_rx_hist_add_entry(&hcrx->ccid3hcrx_hist, packet);
                else {
-                       if (iter->ccid3hrx_type == DCCP_PKT_DATA ||
-                           iter->ccid3hrx_type == DCCP_PKT_DATAACK)
+                       if (dccp_rx_hist_entry_data_packet(iter))
                                num_later = 1;
 
-                       list_for_each_entry_continue(iter, &hcrx->ccid3hcrx_hist, ccid3hrx_node) {
-                               if (after48(seqno, iter->ccid3hrx_seqno)) {
-                                       list_add(&packet->ccid3hrx_node, &iter->ccid3hrx_node);
+                       list_for_each_entry_continue(iter,
+                                                    &hcrx->ccid3hcrx_hist,
+                                                    dccphrx_node) {
+                               if (after48(seqno, iter->dccphrx_seqno)) {
+                                       dccp_rx_hist_add_entry(&iter->dccphrx_node,
+                                                              packet);
                                        goto trim_history;
                                }
 
-                               if (iter->ccid3hrx_type == DCCP_PKT_DATA ||
-                                   iter->ccid3hrx_type == DCCP_PKT_DATAACK)
+                               if (dccp_rx_hist_entry_data_packet(iter))
                                        num_later++;
 
                                if (num_later == TFRC_RECV_NUM_LATE_LOSS) {
-                                       ccid3_rx_hist_entry_delete(packet);
+                                       dccp_rx_hist_entry_delete(ccid3_rx_hist, packet);
                                        ccid3_pr_debug("%s, sk=%p, packet(%llu) already lost!\n",
                                                       dccp_role(sk), sk, seqno);
                                        return 1;
@@ -1504,7 +1442,8 @@ static int ccid3_hc_rx_add_hist(struct sock *sk, struct ccid3_rx_hist_entry *pac
                        }
 
                        if (num_later < TFRC_RECV_NUM_LATE_LOSS)
-                               list_add_tail(&packet->ccid3hrx_node, &hcrx->ccid3hcrx_hist);
+                               dccp_rx_hist_add_entry(&hcrx->ccid3hcrx_hist,
+                                                      packet);
                        /* FIXME: else what? should we destroy the packet like above? */
                }
        }
@@ -1514,12 +1453,12 @@ trim_history:
        num_later = TFRC_RECV_NUM_LATE_LOSS + 1;
 
        if (!list_empty(&hcrx->ccid3hcrx_loss_interval_hist)) {
-               list_for_each_entry_safe(entry, next, &hcrx->ccid3hcrx_hist, ccid3hrx_node) {
+               list_for_each_entry_safe(entry, next, &hcrx->ccid3hcrx_hist,
+                                        dccphrx_node) {
                        if (num_later == 0) {
-                               list_del_init(&entry->ccid3hrx_node);
-                               ccid3_rx_hist_entry_delete(entry);
-                       } else if (entry->ccid3hrx_type == DCCP_PKT_DATA ||
-                                  entry->ccid3hrx_type == DCCP_PKT_DATAACK)
+                               list_del_init(&entry->dccphrx_node);
+                               dccp_rx_hist_entry_delete(ccid3_rx_hist, entry);
+                       } else if (dccp_rx_hist_entry_data_packet(entry))
                                --num_later;
                }
        } else {
@@ -1530,7 +1469,8 @@ trim_history:
                 * We have no loss interval history so we need at least one
                 * rtt:s of data packets to approximate rtt.
                 */
-               list_for_each_entry_safe(entry, next, &hcrx->ccid3hcrx_hist, ccid3hrx_node) {
+               list_for_each_entry_safe(entry, next, &hcrx->ccid3hcrx_hist,
+                                        dccphrx_node) {
                        if (num_later == 0) {
                                switch (step) {
                                case 0:
@@ -1542,10 +1482,10 @@ trim_history:
                                        step = 2;
                                        /* OK, find next data packet */
                                        num_later = 1;
-                                       win_count = entry->ccid3hrx_win_count;
+                                       win_count = entry->dccphrx_ccval;
                                        break;
                                case 2:
-                                       tmp = win_count - entry->ccid3hrx_win_count;
+                                       tmp = win_count - entry->dccphrx_ccval;
                                        if (tmp < 0)
                                                tmp += TFRC_WIN_COUNT_LIMIT;
                                        if (tmp > TFRC_WIN_COUNT_PER_RTT + 1) {
@@ -1556,12 +1496,11 @@ trim_history:
                                                num_later = 1;
                                        break;
                                case 3:
-                                       list_del_init(&entry->ccid3hrx_node);
-                                       ccid3_rx_hist_entry_delete(entry);
+                                       list_del_init(&entry->dccphrx_node);
+                                       dccp_rx_hist_entry_delete(ccid3_rx_hist, entry);
                                        break;
                                }
-                       } else if (entry->ccid3hrx_type == DCCP_PKT_DATA ||
-                                  entry->ccid3hrx_type == DCCP_PKT_DATAACK)
+                       } else if (dccp_rx_hist_entry_data_packet(entry))
                                --num_later;
                }
        }
@@ -1573,7 +1512,7 @@ static void ccid3_hc_rx_send_feedback(struct sock *sk)
 {
        struct dccp_sock *dp = dccp_sk(sk);
        struct ccid3_hc_rx_sock *hcrx = dp->dccps_hc_rx_ccid_private;
-       struct ccid3_rx_hist_entry *entry, *packet;
+       struct dccp_rx_hist_entry *packet;
 
        ccid3_pr_debug("%s, sk=%p\n", dccp_role(sk), sk);
 
@@ -1586,7 +1525,8 @@ static void ccid3_hc_rx_send_feedback(struct sock *sk)
 
                if (delta == 0)
                        delta = 1; /* to prevent divide by zero */
-               hcrx->ccid3hcrx_x_recv = (hcrx->ccid3hcrx_bytes_recv * USEC_IN_SEC) / delta;
+               hcrx->ccid3hcrx_x_recv = (hcrx->ccid3hcrx_bytes_recv *
+                                         USEC_PER_SEC) / delta;
        }
                break;
        default:
@@ -1596,14 +1536,7 @@ static void ccid3_hc_rx_send_feedback(struct sock *sk)
                return;
        }
 
-       packet = NULL;
-       list_for_each_entry(entry, &hcrx->ccid3hcrx_hist, ccid3hrx_node)
-               if (entry->ccid3hrx_type == DCCP_PKT_DATA ||
-                   entry->ccid3hrx_type == DCCP_PKT_DATAACK) {
-                       packet = entry;
-                       break;
-               }
-
+       packet = dccp_rx_hist_find_data_packet(&hcrx->ccid3hcrx_hist);
        if (packet == NULL) {
                printk(KERN_CRIT "%s: %s, sk=%p, no data packet in history!\n",
                       __FUNCTION__, dccp_role(sk), sk);
@@ -1612,12 +1545,12 @@ static void ccid3_hc_rx_send_feedback(struct sock *sk)
        }
 
        do_gettimeofday(&(hcrx->ccid3hcrx_tstamp_last_feedback));
-       hcrx->ccid3hcrx_last_counter         = packet->ccid3hrx_win_count;
-       hcrx->ccid3hcrx_seqno_last_counter   = packet->ccid3hrx_seqno;
+       hcrx->ccid3hcrx_last_counter         = packet->dccphrx_ccval;
+       hcrx->ccid3hcrx_seqno_last_counter   = packet->dccphrx_seqno;
        hcrx->ccid3hcrx_bytes_recv           = 0;
 
        /* Convert to multiples of 10us */
-       hcrx->ccid3hcrx_elapsed_time = now_delta(packet->ccid3hrx_tstamp) / 10;
+       hcrx->ccid3hcrx_elapsed_time = now_delta(packet->dccphrx_tstamp) / 10;
        if (hcrx->ccid3hcrx_p == 0)
                hcrx->ccid3hcrx_pinv = ~0;
        else
@@ -1628,23 +1561,27 @@ static void ccid3_hc_rx_send_feedback(struct sock *sk)
 static void ccid3_hc_rx_insert_options(struct sock *sk, struct sk_buff *skb)
 {
        const struct dccp_sock *dp = dccp_sk(sk);
+       u32 x_recv, pinv;
        struct ccid3_hc_rx_sock *hcrx = dp->dccps_hc_rx_ccid_private;
 
        if (hcrx == NULL || !(sk->sk_state == DCCP_OPEN || sk->sk_state == DCCP_PARTOPEN))
                return;
 
-       if (hcrx->ccid3hcrx_elapsed_time != 0 && !dccp_packet_without_ack(skb))
-               dccp_insert_option_elapsed_time(sk, skb, hcrx->ccid3hcrx_elapsed_time);
-
-       if (DCCP_SKB_CB(skb)->dccpd_type != DCCP_PKT_DATA) {
-               const u32 x_recv = htonl(hcrx->ccid3hcrx_x_recv);
-               const u32 pinv   = htonl(hcrx->ccid3hcrx_pinv);
-
-               dccp_insert_option(sk, skb, TFRC_OPT_LOSS_EVENT_RATE, &pinv, sizeof(pinv));
-               dccp_insert_option(sk, skb, TFRC_OPT_RECEIVE_RATE, &x_recv, sizeof(x_recv));
-       }
-
        DCCP_SKB_CB(skb)->dccpd_ccval = hcrx->ccid3hcrx_last_counter;
+
+       if (dccp_packet_without_ack(skb))
+               return;
+               
+       if (hcrx->ccid3hcrx_elapsed_time != 0)
+               dccp_insert_option_elapsed_time(sk, skb,
+                                               hcrx->ccid3hcrx_elapsed_time);
+       dccp_insert_option_timestamp(sk, skb);
+       x_recv = htonl(hcrx->ccid3hcrx_x_recv);
+       pinv   = htonl(hcrx->ccid3hcrx_pinv);
+       dccp_insert_option(sk, skb, TFRC_OPT_LOSS_EVENT_RATE,
+                          &pinv, sizeof(pinv));
+       dccp_insert_option(sk, skb, TFRC_OPT_RECEIVE_RATE,
+                          &x_recv, sizeof(x_recv));
 }
 
 /* Weights used to calculate loss event rate */
@@ -1652,7 +1589,9 @@ static void ccid3_hc_rx_insert_options(struct sock *sk, struct sk_buff *skb)
  * These are integers as per section 8 of RFC3448. We can then divide by 4 *
  * when we use it.
  */
-const int ccid3_hc_rx_w[TFRC_RECV_IVAL_F_LENGTH] = { 4, 4, 4, 4, 3, 2, 1, 1, };
+static const int ccid3_hc_rx_w[TFRC_RECV_IVAL_F_LENGTH] = {
+       4, 4, 4, 4, 3, 2, 1, 1,
+};
 
 /*
  * args: fvalue - function value to match
@@ -1660,7 +1599,7 @@ const int ccid3_hc_rx_w[TFRC_RECV_IVAL_F_LENGTH] = { 4, 4, 4, 4, 3, 2, 1, 1, };
  *
  * both fvalue and p are multiplied by 1,000,000 to use ints
  */
-u32 calcx_reverse_lookup(u32 fvalue) {
+static u32 calcx_reverse_lookup(u32 fvalue) {
        int ctr = 0;
        int small;
 
@@ -1688,27 +1627,27 @@ static u32 ccid3_hc_rx_calc_first_li(struct sock *sk)
 {
        struct dccp_sock *dp = dccp_sk(sk);
        struct ccid3_hc_rx_sock *hcrx = dp->dccps_hc_rx_ccid_private;
-       struct ccid3_rx_hist_entry *entry, *next, *tail = NULL;
+       struct dccp_rx_hist_entry *entry, *next, *tail = NULL;
        u32 rtt, delta, x_recv, fval, p, tmp2;
-       struct timeval tstamp, tmp_tv;
+       struct timeval tstamp = { 0 }, tmp_tv;
        int interval = 0;
        int win_count = 0;
        int step = 0;
        u64 tmp1;
 
-       list_for_each_entry_safe(entry, next, &hcrx->ccid3hcrx_hist, ccid3hrx_node) {
-               if (entry->ccid3hrx_type == DCCP_PKT_DATA ||
-                   entry->ccid3hrx_type == DCCP_PKT_DATAACK) {
+       list_for_each_entry_safe(entry, next, &hcrx->ccid3hcrx_hist,
+                                dccphrx_node) {
+               if (dccp_rx_hist_entry_data_packet(entry)) {
                        tail = entry;
 
                        switch (step) {
                        case 0:
-                               tstamp    = entry->ccid3hrx_tstamp;
-                               win_count = entry->ccid3hrx_win_count;
+                               tstamp    = entry->dccphrx_tstamp;
+                               win_count = entry->dccphrx_ccval;
                                step = 1;
                                break;
                        case 1:
-                               interval = win_count - entry->ccid3hrx_win_count;
+                               interval = win_count - entry->dccphrx_ccval;
                                if (interval < 0)
                                        interval += TFRC_WIN_COUNT_LIMIT;
                                if (interval > 4)
@@ -1730,8 +1669,8 @@ static u32 ccid3_hc_rx_calc_first_li(struct sock *sk)
                interval = 1;
        }
 found:
-       timeval_sub(tstamp,tail->ccid3hrx_tstamp,&tmp_tv);
-       rtt = (tmp_tv.tv_sec * USEC_IN_SEC + tmp_tv.tv_usec) * 4 / interval;
+       timeval_sub(tstamp,tail->dccphrx_tstamp,&tmp_tv);
+       rtt = (tmp_tv.tv_sec * USEC_PER_SEC + tmp_tv.tv_usec) * 4 / interval;
        ccid3_pr_debug("%s, sk=%p, approximated RTT to %uus\n",
                       dccp_role(sk), sk, rtt);
        if (rtt == 0)
@@ -1741,7 +1680,7 @@ found:
        if (delta == 0)
                delta = 1;
 
-       x_recv = (hcrx->ccid3hcrx_bytes_recv * USEC_IN_SEC) / delta;
+       x_recv = (hcrx->ccid3hcrx_bytes_recv * USEC_PER_SEC) / delta;
 
        tmp1 = (u64)x_recv * (u64)rtt;
        do_div(tmp1,10000000);
@@ -1799,38 +1738,35 @@ static void ccid3_hc_rx_detect_loss(struct sock *sk)
 {
        struct dccp_sock *dp = dccp_sk(sk);
        struct ccid3_hc_rx_sock *hcrx = dp->dccps_hc_rx_ccid_private;
-       struct ccid3_rx_hist_entry *entry, *a_next, *b_next, *packet;
-       struct ccid3_rx_hist_entry *a_loss = NULL;
-       struct ccid3_rx_hist_entry *b_loss = NULL;
+       struct dccp_rx_hist_entry *entry, *next, *packet;
+       struct dccp_rx_hist_entry *a_loss = NULL;
+       struct dccp_rx_hist_entry *b_loss = NULL;
        u64 seq_loss = DCCP_MAX_SEQNO + 1;
        u8 win_loss = 0;
        u8 num_later = TFRC_RECV_NUM_LATE_LOSS;
 
-       list_for_each_entry_safe(entry, b_next, &hcrx->ccid3hcrx_hist, ccid3hrx_node) {
+       list_for_each_entry_safe(entry, next, &hcrx->ccid3hcrx_hist,
+                                dccphrx_node) {
                if (num_later == 0) {
                        b_loss = entry;
                        break;
-               } else if (entry->ccid3hrx_type == DCCP_PKT_DATA ||
-                          entry->ccid3hrx_type == DCCP_PKT_DATAACK)
+               } else if (dccp_rx_hist_entry_data_packet(entry))
                        --num_later;
        }
 
        if (b_loss == NULL)
                goto out_update_li;
 
-       a_next = b_next;
        num_later = 1;
-#if 0
-               FIXME MERGE GIT!
-       list_for_each_entry_safe_continue(entry, a_next, &hcrx->ccid3hcrx_hist, ccid3hrx_node) {
+
+       list_for_each_entry_safe_continue(entry, next, &hcrx->ccid3hcrx_hist,
+                                         dccphrx_node) {
                if (num_later == 0) {
                        a_loss = entry;
                        break;
-               } else if (entry->ccid3hrx_type == DCCP_PKT_DATA ||
-                          entry->ccid3hrx_type == DCCP_PKT_DATAACK)
+               } else if (dccp_rx_hist_entry_data_packet(entry))
                        --num_later;
        }
-#endif
 
        if (a_loss == NULL) {
                if (list_empty(&hcrx->ccid3hcrx_loss_interval_hist)) {
@@ -1848,14 +1784,13 @@ static void ccid3_hc_rx_detect_loss(struct sock *sk)
 
        /* Locate a lost data packet */
        entry = packet = b_loss;
-#if 0
-               FIXME MERGE GIT!
-       list_for_each_entry_safe_continue(entry, b_next, &hcrx->ccid3hcrx_hist, ccid3hrx_node) {
-               u64 delta = dccp_delta_seqno(entry->ccid3hrx_seqno, packet->ccid3hrx_seqno);
+       list_for_each_entry_safe_continue(entry, next, &hcrx->ccid3hcrx_hist,
+                                         dccphrx_node) {
+               u64 delta = dccp_delta_seqno(entry->dccphrx_seqno,
+                                            packet->dccphrx_seqno);
 
                if (delta != 0) {
-                       if (packet->ccid3hrx_type == DCCP_PKT_DATA ||
-                           packet->ccid3hrx_type == DCCP_PKT_DATAACK)
+                       if (dccp_rx_hist_entry_data_packet(packet))
                                --delta;
                        /*
                         * FIXME: check this, probably this % usage is because
@@ -1864,10 +1799,12 @@ static void ccid3_hc_rx_detect_loss(struct sock *sk)
                         */
 #if 0
                        if (delta % DCCP_NDP_LIMIT !=
-                           (packet->ccid3hrx_ndp - entry->ccid3hrx_ndp) % DCCP_NDP_LIMIT)
+                           (packet->dccphrx_ndp -
+                            entry->dccphrx_ndp) % DCCP_NDP_LIMIT)
 #endif
-                       if (delta != packet->ccid3hrx_ndp - entry->ccid3hrx_ndp) {
-                               seq_loss = entry->ccid3hrx_seqno;
+                       if (delta !=
+                            packet->dccphrx_ndp - entry->dccphrx_ndp) {
+                               seq_loss = entry->dccphrx_seqno;
                                dccp_inc_seqno(&seq_loss);
                        }
                }
@@ -1875,10 +1812,9 @@ static void ccid3_hc_rx_detect_loss(struct sock *sk)
                if (packet == a_loss)
                        break;
        }
-#endif
 
        if (seq_loss != DCCP_MAX_SEQNO + 1)
-               win_loss = a_loss->ccid3hrx_win_count;
+               win_loss = a_loss->dccphrx_ccval;
 
 out_update_li:
        ccid3_hc_rx_update_li(sk, seq_loss, win_loss);
@@ -1927,8 +1863,10 @@ static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb)
 {
        struct dccp_sock *dp = dccp_sk(sk);
        struct ccid3_hc_rx_sock *hcrx = dp->dccps_hc_rx_ccid_private;
-       struct ccid3_rx_hist_entry *packet;
+       const struct dccp_options_received *opt_recv;
+       struct dccp_rx_hist_entry *packet;
        struct timeval now;
+       u32 now_usecs;
        u8 win_count;
        u32 p_prev;
        int ins;
@@ -1943,24 +1881,25 @@ static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb)
        BUG_ON(!(hcrx->ccid3hcrx_state == TFRC_RSTATE_NO_DATA ||
                 hcrx->ccid3hcrx_state == TFRC_RSTATE_DATA));
 
+       opt_recv = &dp->dccps_options_received;
+
        switch (DCCP_SKB_CB(skb)->dccpd_type) {
        case DCCP_PKT_ACK:
                if (hcrx->ccid3hcrx_state == TFRC_RSTATE_NO_DATA)
                        return;
        case DCCP_PKT_DATAACK:
-               if (dp->dccps_options_received.dccpor_timestamp_echo == 0)
+               if (opt_recv->dccpor_timestamp_echo == 0)
                        break;
                p_prev = hcrx->ccid3hcrx_rtt;
                do_gettimeofday(&now);
-               /* hcrx->ccid3hcrx_rtt = now - dp->dccps_options_received.dccpor_timestamp_echo -
-                                     usecs_to_jiffies(dp->dccps_options_received.dccpor_elapsed_time * 10);
-               FIXME - I think above code is broken - have to look at options more, will also need
-               to fix pr_debug below */
+               now_usecs = now.tv_sec * USEC_PER_SEC + now.tv_usec;
+               hcrx->ccid3hcrx_rtt = now_usecs -
+                                    (opt_recv->dccpor_timestamp_echo -
+                                     opt_recv->dccpor_elapsed_time) * 10;
                if (p_prev != hcrx->ccid3hcrx_rtt)
-                       ccid3_pr_debug("%s, sk=%p, New RTT estimate=%lu jiffies, tstamp_echo=%u, elapsed time=%u\n",
-                                      dccp_role(sk), sk, hcrx->ccid3hcrx_rtt,
-                                      dp->dccps_options_received.dccpor_timestamp_echo,
-                                      dp->dccps_options_received.dccpor_elapsed_time);
+                       ccid3_pr_debug("%s, New RTT=%luus, elapsed time=%u\n",
+                                      dccp_role(sk), hcrx->ccid3hcrx_rtt,
+                                      opt_recv->dccpor_elapsed_time);
                break;
        case DCCP_PKT_DATA:
                break;
@@ -1971,14 +1910,15 @@ static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb)
                return;
        }
 
-       packet = ccid3_rx_hist_entry_new(sk, skb, SLAB_ATOMIC);
+       packet = dccp_rx_hist_entry_new(ccid3_rx_hist, opt_recv->dccpor_ndp,
+                                       skb, SLAB_ATOMIC);
        if (packet == NULL) {
                ccid3_pr_debug("%s, sk=%p, Not enough mem to add rx packet to history (consider it lost)!",
                               dccp_role(sk), sk);
                return;
        }
 
-       win_count = packet->ccid3hrx_win_count;
+       win_count = packet->dccphrx_ccval;
 
        ins = ccid3_hc_rx_add_hist(sk, packet);
 
@@ -1995,9 +1935,9 @@ static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb)
        case TFRC_RSTATE_DATA:
                hcrx->ccid3hcrx_bytes_recv += skb->len - dccp_hdr(skb)->dccph_doff * 4;
                if (ins == 0) {
-                       do_gettimeofday(&now);
-                       if ((now_delta(hcrx->ccid3hcrx_tstamp_last_ack)) >= hcrx->ccid3hcrx_rtt) {
-                               hcrx->ccid3hcrx_tstamp_last_ack = now;
+                       if (now_delta(hcrx->ccid3hcrx_tstamp_last_ack) >=
+                           hcrx->ccid3hcrx_rtt) {
+                               do_gettimeofday(&hcrx->ccid3hcrx_tstamp_last_ack);
                                ccid3_hc_rx_send_feedback(sk);
                        }
                        return;
@@ -2011,8 +1951,8 @@ static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb)
        }
 
        /* Dealing with packet loss */
-       ccid3_pr_debug("%s, sk=%p(%s), skb=%p, data loss! Reacting...\n",
-                      dccp_role(sk), sk, dccp_state_name(sk->sk_state), skb);
+       ccid3_pr_debug("%s, sk=%p(%s), data loss! Reacting...\n",
+                      dccp_role(sk), sk, dccp_state_name(sk->sk_state));
 
        ccid3_hc_rx_detect_loss(sk);
        p_prev = hcrx->ccid3hcrx_p;
@@ -2050,7 +1990,11 @@ static int ccid3_hc_rx_init(struct sock *sk)
        hcrx->ccid3hcrx_state = TFRC_RSTATE_NO_DATA;
        INIT_LIST_HEAD(&hcrx->ccid3hcrx_hist);
        INIT_LIST_HEAD(&hcrx->ccid3hcrx_loss_interval_hist);
-
+       /*
+        * XXX this seems to be paranoid, need to think more about this, for
+        * now start with something different than zero. -acme
+        */
+       hcrx->ccid3hcrx_rtt = USEC_PER_SEC / 5;
        return 0;
 }
 
@@ -2067,7 +2011,7 @@ static void ccid3_hc_rx_exit(struct sock *sk)
        ccid3_hc_rx_set_state(sk, TFRC_RSTATE_TERM);
 
        /* Empty packet history */
-       ccid3_rx_history_delete(&hcrx->ccid3hcrx_hist);
+       dccp_rx_hist_purge(ccid3_rx_hist, &hcrx->ccid3hcrx_hist);
 
        /* Empty loss interval history */
        ccid3_loss_interval_history_delete(&hcrx->ccid3hcrx_loss_interval_hist);
@@ -2076,6 +2020,31 @@ static void ccid3_hc_rx_exit(struct sock *sk)
        dp->dccps_hc_rx_ccid_private = NULL;
 }
 
+static void ccid3_hc_rx_get_info(struct sock *sk, struct tcp_info *info)
+{
+       const struct dccp_sock *dp = dccp_sk(sk);
+       const struct ccid3_hc_rx_sock *hcrx = dp->dccps_hc_rx_ccid_private;
+
+       if (hcrx == NULL)
+               return;
+
+       info->tcpi_ca_state     = hcrx->ccid3hcrx_state;
+       info->tcpi_options      |= TCPI_OPT_TIMESTAMPS;
+       info->tcpi_rcv_rtt      = hcrx->ccid3hcrx_rtt;
+}
+
+static void ccid3_hc_tx_get_info(struct sock *sk, struct tcp_info *info)
+{
+       const struct dccp_sock *dp = dccp_sk(sk);
+       const struct ccid3_hc_tx_sock *hctx = dp->dccps_hc_tx_ccid_private;
+
+       if (hctx == NULL)
+               return;
+
+       info->tcpi_rto = hctx->ccid3hctx_t_rto;
+       info->tcpi_rtt = hctx->ccid3hctx_rtt;
+}
+
 static struct ccid ccid3 = {
        .ccid_id                   = 3,
        .ccid_name                 = "ccid3",
@@ -2093,6 +2062,8 @@ static struct ccid ccid3 = {
        .ccid_hc_rx_exit           = ccid3_hc_rx_exit,
        .ccid_hc_rx_insert_options = ccid3_hc_rx_insert_options,
        .ccid_hc_rx_packet_recv    = ccid3_hc_rx_packet_recv,
+       .ccid_hc_rx_get_info       = ccid3_hc_rx_get_info,
+       .ccid_hc_tx_get_info       = ccid3_hc_tx_get_info,
 };
  
 module_param(ccid3_debug, int, 0444);
@@ -2100,56 +2071,62 @@ MODULE_PARM_DESC(ccid3_debug, "Enable debug messages");
 
 static __init int ccid3_module_init(void)
 {
-       int rc = -ENOMEM;
+       int rc = -ENOBUFS;
 
-       ccid3_tx_hist_slab = kmem_cache_create("dccp_ccid3_tx_history",
-                                              sizeof(struct ccid3_tx_hist_entry), 0,
-                                              SLAB_HWCACHE_ALIGN, NULL, NULL);
-       if (ccid3_tx_hist_slab == NULL)
+       ccid3_rx_hist = dccp_rx_hist_new("ccid3");
+       if (ccid3_rx_hist == NULL)
                goto out;
 
-       ccid3_rx_hist_slab = kmem_cache_create("dccp_ccid3_rx_history",
-                                              sizeof(struct ccid3_rx_hist_entry), 0,
-                                              SLAB_HWCACHE_ALIGN, NULL, NULL);
-       if (ccid3_rx_hist_slab == NULL)
-               goto out_free_tx_history;
+       ccid3_tx_hist = dccp_tx_hist_new("ccid3");
+       if (ccid3_tx_hist == NULL)
+               goto out_free_rx;
 
-       ccid3_loss_interval_hist_slab = kmem_cache_create("dccp_ccid3_loss_interval_history",
-                                                         sizeof(struct ccid3_loss_interval_hist_entry), 0,
-                                                         SLAB_HWCACHE_ALIGN, NULL, NULL);
+       ccid3_loss_interval_hist_slab = kmem_cache_create("li_hist_ccid3",
+                                 sizeof(struct ccid3_loss_interval_hist_entry),
+                                                         0, SLAB_HWCACHE_ALIGN,
+                                                         NULL, NULL);
        if (ccid3_loss_interval_hist_slab == NULL)
-               goto out_free_rx_history;
+               goto out_free_tx;
 
        rc = ccid_register(&ccid3);
        if (rc != 0) 
                goto out_free_loss_interval_history;
-
 out:
        return rc;
+
 out_free_loss_interval_history:
        kmem_cache_destroy(ccid3_loss_interval_hist_slab);
        ccid3_loss_interval_hist_slab = NULL;
-out_free_rx_history:
-       kmem_cache_destroy(ccid3_rx_hist_slab);
-       ccid3_rx_hist_slab = NULL;
-out_free_tx_history:
-       kmem_cache_destroy(ccid3_tx_hist_slab);
-       ccid3_tx_hist_slab = NULL;
+out_free_tx:
+       dccp_tx_hist_delete(ccid3_tx_hist);
+       ccid3_tx_hist = NULL;
+out_free_rx:
+       dccp_rx_hist_delete(ccid3_rx_hist);
+       ccid3_rx_hist = NULL;
        goto out;
 }
 module_init(ccid3_module_init);
 
 static __exit void ccid3_module_exit(void)
 {
+#ifdef CONFIG_IP_DCCP_UNLOAD_HACK
+       /*
+        * Hack to use while developing, so that we get rid of the control
+        * sock, that is what keeps a refcount on dccp.ko -acme
+        */
+       extern void dccp_ctl_sock_exit(void);
+
+       dccp_ctl_sock_exit();
+#endif
        ccid_unregister(&ccid3);
 
-       if (ccid3_tx_hist_slab != NULL) {
-               kmem_cache_destroy(ccid3_tx_hist_slab);
-               ccid3_tx_hist_slab = NULL;
+       if (ccid3_tx_hist != NULL) {
+               dccp_tx_hist_delete(ccid3_tx_hist);
+               ccid3_tx_hist = NULL;
        }
-       if (ccid3_rx_hist_slab != NULL) {
-               kmem_cache_destroy(ccid3_rx_hist_slab);
-               ccid3_rx_hist_slab = NULL;
+       if (ccid3_rx_hist != NULL) {
+               dccp_rx_hist_delete(ccid3_rx_hist);
+               ccid3_rx_hist = NULL;
        }
        if (ccid3_loss_interval_hist_slab != NULL) {
                kmem_cache_destroy(ccid3_loss_interval_hist_slab);
This page took 0.054125 seconds and 5 git commands to generate.