summaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorArnaldo Carvalho de Melo <acme@ghostprotocols.net>2005-08-09 20:14:34 -0700
committerDavid S. Miller <davem@sunset.davemloft.net>2005-08-29 15:49:46 -0700
commit7c657876b63cb1d8a2ec06f8fc6c37bb8412e66c (patch)
tree3cb2732870c9cf8f976cb6fa57e0223f1c648e2a /net
parentc4365c9235f80128c3c3d5993074173941b1c1f0 (diff)
[DCCP]: Initial implementation
Development to this point was done on a subversion repository at: http://oops.ghostprotocols.net:81/cgi-bin/viewcvs.cgi/dccp-2.6/ This repository will be kept at this site for the foreseable future, so that interested parties can see the history of this code, attributions, etc. If I ever decide to take this offline I'll provide the full history at some other suitable place. Signed-off-by: Arnaldo Carvalho de Melo <acme@ghostprotocols.net> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r--net/Kconfig1
-rw-r--r--net/Makefile1
-rw-r--r--net/dccp/Kconfig24
-rw-r--r--net/dccp/Makefile5
-rw-r--r--net/dccp/ccid.c139
-rw-r--r--net/dccp/ccid.h156
-rw-r--r--net/dccp/ccids/Kconfig25
-rw-r--r--net/dccp/ccids/Makefile3
-rw-r--r--net/dccp/ccids/ccid3.c2164
-rw-r--r--net/dccp/ccids/ccid3.h137
-rw-r--r--net/dccp/dccp.h422
-rw-r--r--net/dccp/input.c510
-rw-r--r--net/dccp/ipv4.c1289
-rw-r--r--net/dccp/minisocks.c199
-rw-r--r--net/dccp/options.c763
-rw-r--r--net/dccp/output.c406
-rw-r--r--net/dccp/proto.c818
-rw-r--r--net/dccp/timer.c249
18 files changed, 7311 insertions, 0 deletions
diff --git a/net/Kconfig b/net/Kconfig
index 02877ac0f2f4..c07aafb59a0f 100644
--- a/net/Kconfig
+++ b/net/Kconfig
@@ -147,6 +147,7 @@ source "net/bridge/netfilter/Kconfig"
endif
+source "net/dccp/Kconfig"
source "net/sctp/Kconfig"
source "net/atm/Kconfig"
source "net/bridge/Kconfig"
diff --git a/net/Makefile b/net/Makefile
index 4a01be8d3e1e..7e6eff206c81 100644
--- a/net/Makefile
+++ b/net/Makefile
@@ -42,6 +42,7 @@ obj-$(CONFIG_ATM) += atm/
obj-$(CONFIG_DECNET) += decnet/
obj-$(CONFIG_ECONET) += econet/
obj-$(CONFIG_VLAN_8021Q) += 8021q/
+obj-$(CONFIG_IP_DCCP) += dccp/
obj-$(CONFIG_IP_SCTP) += sctp/
ifeq ($(CONFIG_NET),y)
diff --git a/net/dccp/Kconfig b/net/dccp/Kconfig
new file mode 100644
index 000000000000..90460bc629b3
--- /dev/null
+++ b/net/dccp/Kconfig
@@ -0,0 +1,24 @@
+menu "DCCP Configuration (EXPERIMENTAL)"
+ depends on INET && EXPERIMENTAL
+
+config IP_DCCP
+ tristate "The DCCP Protocol (EXPERIMENTAL)"
+ ---help---
+ Datagram Congestion Control Protocol
+
+ From draft-ietf-dccp-spec-11 <http://www.icir.org/kohler/dcp/draft-ietf-dccp-spec-11.txt>.
+
+ The Datagram Congestion Control Protocol (DCCP) is a transport
+ protocol that implements bidirectional, unicast connections of
+ congestion-controlled, unreliable datagrams. It should be suitable
+ for use by applications such as streaming media, Internet telephony,
+ and on-line games
+
+ To compile this protocol support as a module, choose M here: the
+ module will be called dccp.
+
+ If in doubt, say N.
+
+source "net/dccp/ccids/Kconfig"
+
+endmenu
diff --git a/net/dccp/Makefile b/net/dccp/Makefile
new file mode 100644
index 000000000000..c6e6ba55c36b
--- /dev/null
+++ b/net/dccp/Makefile
@@ -0,0 +1,5 @@
+obj-$(CONFIG_IP_DCCP) += dccp.o
+
+dccp-y := ccid.o input.o ipv4.o minisocks.o options.o output.o proto.o timer.o
+
+obj-y += ccids/
diff --git a/net/dccp/ccid.c b/net/dccp/ccid.c
new file mode 100644
index 000000000000..9d8fc0e289ea
--- /dev/null
+++ b/net/dccp/ccid.c
@@ -0,0 +1,139 @@
+/*
+ * net/dccp/ccid.c
+ *
+ * An implementation of the DCCP protocol
+ * Arnaldo Carvalho de Melo <acme@conectiva.com.br>
+ *
+ * CCID infrastructure
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include "ccid.h"
+
+static struct ccid *ccids[CCID_MAX];
+#if defined(CONFIG_SMP) || defined(CONFIG_PREEMPT)
+static atomic_t ccids_lockct = ATOMIC_INIT(0);
+static DEFINE_SPINLOCK(ccids_lock);
+
+/*
+ * The strategy is: modifications ccids vector are short, do not sleep and
+ * veeery rare, but read access should be free of any exclusive locks.
+ */
+static void ccids_write_lock(void)
+{
+ spin_lock(&ccids_lock);
+ while (atomic_read(&ccids_lockct) != 0) {
+ spin_unlock(&ccids_lock);
+ yield();
+ spin_lock(&ccids_lock);
+ }
+}
+
+static inline void ccids_write_unlock(void)
+{
+ spin_unlock(&ccids_lock);
+}
+
+static inline void ccids_read_lock(void)
+{
+ atomic_inc(&ccids_lockct);
+ spin_unlock_wait(&ccids_lock);
+}
+
+static inline void ccids_read_unlock(void)
+{
+ atomic_dec(&ccids_lockct);
+}
+
+#else
+#define ccids_write_lock() do { } while(0)
+#define ccids_write_unlock() do { } while(0)
+#define ccids_read_lock() do { } while(0)
+#define ccids_read_unlock() do { } while(0)
+#endif
+
+int ccid_register(struct ccid *ccid)
+{
+ int err;
+
+ if (ccid->ccid_init == NULL)
+ return -1;
+
+ ccids_write_lock();
+ err = -EEXIST;
+ if (ccids[ccid->ccid_id] == NULL) {
+ ccids[ccid->ccid_id] = ccid;
+ err = 0;
+ }
+ ccids_write_unlock();
+ if (err == 0)
+ pr_info("CCID: Registered CCID %d (%s)\n",
+ ccid->ccid_id, ccid->ccid_name);
+ return err;
+}
+
+EXPORT_SYMBOL_GPL(ccid_register);
+
+int ccid_unregister(struct ccid *ccid)
+{
+ ccids_write_lock();
+ ccids[ccid->ccid_id] = NULL;
+ ccids_write_unlock();
+ pr_info("CCID: Unregistered CCID %d (%s)\n",
+ ccid->ccid_id, ccid->ccid_name);
+ return 0;
+}
+
+EXPORT_SYMBOL_GPL(ccid_unregister);
+
+struct ccid *ccid_init(unsigned char id, struct sock *sk)
+{
+ struct ccid *ccid;
+
+#ifdef CONFIG_KMOD
+ if (ccids[id] == NULL)
+ request_module("net-dccp-ccid-%d", id);
+#endif
+ ccids_read_lock();
+
+ ccid = ccids[id];
+ if (ccid == NULL)
+ goto out;
+
+ if (!try_module_get(ccid->ccid_owner))
+ goto out_err;
+
+ if (ccid->ccid_init(sk) != 0)
+ goto out_module_put;
+out:
+ ccids_read_unlock();
+ return ccid;
+out_module_put:
+ module_put(ccid->ccid_owner);
+out_err:
+ ccid = NULL;
+ goto out;
+}
+
+EXPORT_SYMBOL_GPL(ccid_init);
+
+void ccid_exit(struct ccid *ccid, struct sock *sk)
+{
+ if (ccid == NULL)
+ return;
+
+ ccids_read_lock();
+
+ if (ccids[ccid->ccid_id] != NULL) {
+ if (ccid->ccid_exit != NULL)
+ ccid->ccid_exit(sk);
+ module_put(ccid->ccid_owner);
+ }
+
+ ccids_read_unlock();
+}
+
+EXPORT_SYMBOL_GPL(ccid_exit);
diff --git a/net/dccp/ccid.h b/net/dccp/ccid.h
new file mode 100644
index 000000000000..06105b2a613c
--- /dev/null
+++ b/net/dccp/ccid.h
@@ -0,0 +1,156 @@
+#ifndef _CCID_H
+#define _CCID_H
+/*
+ * net/dccp/ccid.h
+ *
+ * An implementation of the DCCP protocol
+ * Arnaldo Carvalho de Melo <acme@conectiva.com.br>
+ *
+ * CCID infrastructure
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <net/sock.h>
+#include <linux/dccp.h>
+#include <linux/list.h>
+#include <linux/module.h>
+
+#define CCID_MAX 255
+
+struct ccid {
+ unsigned char ccid_id;
+ const char *ccid_name;
+ struct module *ccid_owner;
+ int (*ccid_init)(struct sock *sk);
+ void (*ccid_exit)(struct sock *sk);
+ int (*ccid_hc_rx_init)(struct sock *sk);
+ int (*ccid_hc_tx_init)(struct sock *sk);
+ void (*ccid_hc_rx_exit)(struct sock *sk);
+ void (*ccid_hc_tx_exit)(struct sock *sk);
+ void (*ccid_hc_rx_packet_recv)(struct sock *sk, struct sk_buff *skb);
+ int (*ccid_hc_rx_parse_options)(struct sock *sk,
+ unsigned char option,
+ unsigned char len, u16 idx,
+ unsigned char* value);
+ void (*ccid_hc_rx_insert_options)(struct sock *sk, struct sk_buff *skb);
+ void (*ccid_hc_tx_insert_options)(struct sock *sk, struct sk_buff *skb);
+ void (*ccid_hc_tx_packet_recv)(struct sock *sk, struct sk_buff *skb);
+ int (*ccid_hc_tx_parse_options)(struct sock *sk,
+ unsigned char option,
+ unsigned char len, u16 idx,
+ unsigned char* value);
+ int (*ccid_hc_tx_send_packet)(struct sock *sk,
+ struct sk_buff *skb, int len,
+ long *delay);
+ void (*ccid_hc_tx_packet_sent)(struct sock *sk, int more, int len);
+};
+
+extern int ccid_register(struct ccid *ccid);
+extern int ccid_unregister(struct ccid *ccid);
+
+extern struct ccid *ccid_init(unsigned char id, struct sock *sk);
+extern void ccid_exit(struct ccid *ccid, struct sock *sk);
+
+static inline void __ccid_get(struct ccid *ccid)
+{
+ __module_get(ccid->ccid_owner);
+}
+
+static inline int ccid_hc_tx_send_packet(struct ccid *ccid, struct sock *sk,
+ struct sk_buff *skb, int len,
+ long *delay)
+{
+ int rc = 0;
+ if (ccid->ccid_hc_tx_send_packet != NULL)
+ rc = ccid->ccid_hc_tx_send_packet(sk, skb, len, delay);
+ return rc;
+}
+
+static inline void ccid_hc_tx_packet_sent(struct ccid *ccid, struct sock *sk,
+ int more, int len)
+{
+ if (ccid->ccid_hc_tx_packet_sent != NULL)
+ ccid->ccid_hc_tx_packet_sent(sk, more, len);
+}
+
+static inline int ccid_hc_rx_init(struct ccid *ccid, struct sock *sk)
+{
+ int rc = 0;
+ if (ccid->ccid_hc_rx_init != NULL)
+ rc = ccid->ccid_hc_rx_init(sk);
+ return rc;
+}
+
+static inline int ccid_hc_tx_init(struct ccid *ccid, struct sock *sk)
+{
+ int rc = 0;
+ if (ccid->ccid_hc_tx_init != NULL)
+ rc = ccid->ccid_hc_tx_init(sk);
+ return rc;
+}
+
+static inline void ccid_hc_rx_exit(struct ccid *ccid, struct sock *sk)
+{
+ if (ccid->ccid_hc_rx_exit != NULL)
+ ccid->ccid_hc_rx_exit(sk);
+}
+
+static inline void ccid_hc_tx_exit(struct ccid *ccid, struct sock *sk)
+{
+ if (ccid->ccid_hc_tx_exit != NULL)
+ ccid->ccid_hc_tx_exit(sk);
+}
+
+static inline void ccid_hc_rx_packet_recv(struct ccid *ccid, struct sock *sk,
+ struct sk_buff *skb)
+{
+ if (ccid->ccid_hc_rx_packet_recv != NULL)
+ ccid->ccid_hc_rx_packet_recv(sk, skb);
+}
+
+static inline void ccid_hc_tx_packet_recv(struct ccid *ccid, struct sock *sk,
+ struct sk_buff *skb)
+{
+ if (ccid->ccid_hc_tx_packet_recv != NULL)
+ ccid->ccid_hc_tx_packet_recv(sk, skb);
+}
+
+static inline int ccid_hc_tx_parse_options(struct ccid *ccid, struct sock *sk,
+ unsigned char option,
+ unsigned char len, u16 idx,
+ unsigned char* value)
+{
+ int rc = 0;
+ if (ccid->ccid_hc_tx_parse_options != NULL)
+ rc = ccid->ccid_hc_tx_parse_options(sk, option, len, idx, value);
+ return rc;
+}
+
+static inline int ccid_hc_rx_parse_options(struct ccid *ccid, struct sock *sk,
+ unsigned char option,
+ unsigned char len, u16 idx,
+ unsigned char* value)
+{
+ int rc = 0;
+ if (ccid->ccid_hc_rx_parse_options != NULL)
+ rc = ccid->ccid_hc_rx_parse_options(sk, option, len, idx, value);
+ return rc;
+}
+
+static inline void ccid_hc_tx_insert_options(struct ccid *ccid, struct sock *sk,
+ struct sk_buff *skb)
+{
+ if (ccid->ccid_hc_tx_insert_options != NULL)
+ ccid->ccid_hc_tx_insert_options(sk, skb);
+}
+
+static inline void ccid_hc_rx_insert_options(struct ccid *ccid, struct sock *sk,
+ struct sk_buff *skb)
+{
+ if (ccid->ccid_hc_rx_insert_options != NULL)
+ ccid->ccid_hc_rx_insert_options(sk, skb);
+}
+#endif /* _CCID_H */
diff --git a/net/dccp/ccids/Kconfig b/net/dccp/ccids/Kconfig
new file mode 100644
index 000000000000..67f9c06bd179
--- /dev/null
+++ b/net/dccp/ccids/Kconfig
@@ -0,0 +1,25 @@
+menu "DCCP CCIDs Configuration (EXPERIMENTAL)"
+ depends on IP_DCCP && EXPERIMENTAL
+
+config IP_DCCP_CCID3
+ tristate "CCID3 (TFRC) (EXPERIMENTAL)"
+ depends on IP_DCCP
+ ---help---
+ CCID 3 denotes TCP-Friendly Rate Control (TFRC), an equation-based
+ rate-controlled congestion control mechanism. TFRC is designed to
+ be reasonably fair when competing for bandwidth with TCP-like flows,
+ where a flow is "reasonably fair" if its sending rate is generally
+ within a factor of two of the sending rate of a TCP flow under the
+ same conditions. However, TFRC has a much lower variation of
+ throughput over time compared with TCP, which makes CCID 3 more
+ suitable than CCID 2 for applications such streaming media where a
+ relatively smooth sending rate is of importance.
+
+ CCID 3 is further described in [CCID 3 PROFILE]. The TFRC
+ congestion control algorithms were initially described in RFC 3448.
+
+ This text was extracted from draft-ietf-dccp-spec-11.txt.
+
+ If in doubt, say M.
+
+endmenu
diff --git a/net/dccp/ccids/Makefile b/net/dccp/ccids/Makefile
new file mode 100644
index 000000000000..1c720131c5db
--- /dev/null
+++ b/net/dccp/ccids/Makefile
@@ -0,0 +1,3 @@
+obj-$(CONFIG_IP_DCCP_CCID3) += dccp_ccid3.o
+
+dccp_ccid3-y := ccid3.o
diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c
new file mode 100644
index 000000000000..4f45902cb55e
--- /dev/null
+++ b/net/dccp/ccids/ccid3.c
@@ -0,0 +1,2164 @@
+/*
+ * net/dccp/ccids/ccid3.c
+ *
+ * Copyright (c) 2005 The University of Waikato, Hamilton, New Zealand.
+ *
+ * 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:
+ * Copyright (c) 2003 Nils-Erik Mattsson, Joacim Haggmark, Magnus Erixzon
+ *
+ * Changes to meet Linux coding standards, to make it meet latest ccid3 draft
+ * and to make it work as a loadable module in the DCCP stack written by
+ * Arnaldo Carvalho de Melo <acme@conectiva.com.br>.
+ *
+ * Copyright (c) 2005 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "../ccid.h"
+#include "../dccp.h"
+#include "ccid3.h"
+
+#ifdef CCID3_DEBUG
+extern int ccid3_debug;
+
+#define ccid3_pr_debug(format, a...) \
+ do { if (ccid3_debug) \
+ printk(KERN_DEBUG "%s: " format, __FUNCTION__, ##a); \
+ } while (0)
+#else
+#define ccid3_pr_debug(format, a...)
+#endif
+
+#define TFRC_MIN_PACKET_SIZE 16
+#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)
+/* two seconds as per CCID3 spec 11 */
+
+#define TFRC_OPSYS_HALF_TIME_GRAN (USEC_IN_SEC / (2 * HZ))
+/* above is in usecs - half the scheduling granularity as per RFC3448 4.6 */
+
+#define TFRC_WIN_COUNT_PER_RTT 4
+#define TFRC_WIN_COUNT_LIMIT 16
+
+#define TFRC_MAX_BACK_OFF_TIME 64
+/* above is in seconds */
+
+#define TFRC_SMALLEST_P 40
+
+#define TFRC_RECV_IVAL_F_LENGTH 8 /* length(w[]) */
+
+/* Number of later packets received before one is considered lost */
+#define TFRC_RECV_NUM_LATE_LOSS 3
+
+enum ccid3_options {
+ TFRC_OPT_LOSS_EVENT_RATE = 192,
+ TFRC_OPT_LOSS_INTERVALS = 193,
+ TFRC_OPT_RECEIVE_RATE = 194,
+};
+
+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 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 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)
+{
+ return kmem_cache_alloc(ccid3_loss_interval_hist_slab, prio);
+}
+
+static inline void ccid3_loss_interval_hist_entry_delete(struct ccid3_loss_interval_hist_entry *entry)
+{
+ if (entry != NULL)
+ kmem_cache_free(ccid3_loss_interval_hist_slab, entry);
+}
+
+static void ccid3_loss_interval_history_delete(struct list_head *hist)
+{
+ struct ccid3_loss_interval_hist_entry *entry, *next;
+
+ list_for_each_entry_safe(entry, next, hist, ccid3lih_node) {
+ list_del_init(&entry->ccid3lih_node);
+ kmem_cache_free(ccid3_loss_interval_hist_slab, entry);
+ }
+}
+
+static int ccid3_init(struct sock *sk)
+{
+ ccid3_pr_debug("%s, sk=%p\n", dccp_role(sk), sk);
+ return 0;
+}
+
+static void ccid3_exit(struct sock *sk)
+{
+ ccid3_pr_debug("%s, sk=%p\n", dccp_role(sk), sk);
+}
+
+/* TFRC sender states */
+enum ccid3_hc_tx_states {
+ TFRC_SSTATE_NO_SENT = 1,
+ TFRC_SSTATE_NO_FBACK,
+ TFRC_SSTATE_FBACK,
+ TFRC_SSTATE_TERM,
+};
+
+#ifdef CCID3_DEBUG
+static const char *ccid3_tx_state_name(enum ccid3_hc_tx_states state)
+{
+ static char *ccid3_state_names[] = {
+ [TFRC_SSTATE_NO_SENT] = "NO_SENT",
+ [TFRC_SSTATE_NO_FBACK] = "NO_FBACK",
+ [TFRC_SSTATE_FBACK] = "FBACK",
+ [TFRC_SSTATE_TERM] = "TERM",
+ };
+
+ return ccid3_state_names[state];
+}
+#endif
+
+static inline void ccid3_hc_tx_set_state(struct sock *sk, enum ccid3_hc_tx_states state)
+{
+ struct dccp_sock *dp = dccp_sk(sk);
+ struct ccid3_hc_tx_sock *hctx = dp->dccps_hc_tx_ccid_private;
+ enum ccid3_hc_tx_states oldstate = hctx->ccid3hctx_state;
+
+ ccid3_pr_debug("%s(%p) %-8.8s -> %s\n",
+ dccp_role(sk), sk, ccid3_tx_state_name(oldstate), ccid3_tx_state_name(state));
+ WARN_ON(state == oldstate);
+ hctx->ccid3hctx_state = state;
+}
+
+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;
+ } 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) {
+ tv->tv_sec++;
+ tv->tv_usec -= USEC_IN_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
+/* equivalent to 0.05 */
+
+static const u32 calcx_lookup[CALCX_ARRSIZE][2] = {
+ { 37172 , 8172 },
+ { 53499 , 11567 },
+ { 66664 , 14180 },
+ { 78298 , 16388 },
+ { 89021 , 18339 },
+ { 99147 , 20108 },
+ { 108858 , 21738 },
+ { 118273 , 23260 },
+ { 127474 , 24693 },
+ { 136520 , 26052 },
+ { 145456 , 27348 },
+ { 154316 , 28589 },
+ { 163130 , 29783 },
+ { 171919 , 30935 },
+ { 180704 , 32049 },
+ { 189502 , 33130 },
+ { 198328 , 34180 },
+ { 207194 , 35202 },
+ { 216114 , 36198 },
+ { 225097 , 37172 },
+ { 234153 , 38123 },
+ { 243294 , 39055 },
+ { 252527 , 39968 },
+ { 261861 , 40864 },
+ { 271305 , 41743 },
+ { 280866 , 42607 },
+ { 290553 , 43457 },
+ { 300372 , 44293 },
+ { 310333 , 45117 },
+ { 320441 , 45929 },
+ { 330705 , 46729 },
+ { 341131 , 47518 },
+ { 351728 , 48297 },
+ { 362501 , 49066 },
+ { 373460 , 49826 },
+ { 384609 , 50577 },
+ { 395958 , 51320 },
+ { 407513 , 52054 },
+ { 419281 , 52780 },
+ { 431270 , 53499 },
+ { 443487 , 54211 },
+ { 455940 , 54916 },
+ { 468635 , 55614 },
+ { 481581 , 56306 },
+ { 494785 , 56991 },
+ { 508254 , 57671 },
+ { 521996 , 58345 },
+ { 536019 , 59014 },
+ { 550331 , 59677 },
+ { 564939 , 60335 },
+ { 579851 , 60988 },
+ { 595075 , 61636 },
+ { 610619 , 62279 },
+ { 626491 , 62918 },
+ { 642700 , 63553 },
+ { 659253 , 64183 },
+ { 676158 , 64809 },
+ { 693424 , 65431 },
+ { 711060 , 66050 },
+ { 729073 , 66664 },
+ { 747472 , 67275 },
+ { 766266 , 67882 },
+ { 785464 , 68486 },
+ { 805073 , 69087 },
+ { 825103 , 69684 },
+ { 845562 , 70278 },
+ { 866460 , 70868 },
+ { 887805 , 71456 },
+ { 909606 , 72041 },
+ { 931873 , 72623 },
+ { 954614 , 73202 },
+ { 977839 , 73778 },
+ { 1001557 , 74352 },
+ { 1025777 , 74923 },
+ { 1050508 , 75492 },
+ { 1075761 , 76058 },
+ { 1101544 , 76621 },
+ { 1127867 , 77183 },
+ { 1154739 , 77741 },
+ { 1182172 , 78298 },
+ { 1210173 , 78852 },
+ { 1238753 , 79405 },
+ { 1267922 , 79955 },
+ { 1297689 , 80503 },
+ { 1328066 , 81049 },
+ { 1359060 , 81593 },
+ { 1390684 , 82135 },
+ { 1422947 , 82675 },
+ { 1455859 , 83213 },
+ { 1489430 , 83750 },
+ { 1523671 , 84284 },
+ { 1558593 , 84817 },
+ { 1594205 , 85348 },
+ { 1630518 , 85878 },
+ { 1667543 , 86406 },
+ { 1705290 , 86932 },
+ { 1743770 , 87457 },
+ { 1782994 , 87980 },
+ { 1822973 , 88501 },
+ { 1863717 , 89021 },
+ { 1905237 , 89540 },
+ { 1947545 , 90057 },
+ { 1990650 , 90573 },
+ { 2034566 , 91087 },
+ { 2079301 , 91600 },
+ { 2124869 , 92111 },
+ { 2171279 , 92622 },
+ { 2218543 , 93131 },
+ { 2266673 , 93639 },
+ { 2315680 , 94145 },
+ { 2365575 , 94650 },
+ { 2416371 , 95154 },
+ { 2468077 , 95657 },
+ { 2520707 , 96159 },
+ { 2574271 , 96660 },
+ { 2628782 , 97159 },
+ { 2684250 , 97658 },
+ { 2740689 , 98155 },
+ { 2798110 , 98651 },
+ { 2856524 , 99147 },
+ { 2915944 , 99641 },
+ { 2976382 , 100134 },
+ { 3037850 , 100626 },
+ { 3100360 , 101117 },
+ { 3163924 , 101608 },
+ { 3228554 , 102097 },
+ { 3294263 , 102586 },
+ { 3361063 , 103073 },
+ { 3428966 , 103560 },
+ { 3497984 , 104045 },
+ { 3568131 , 104530 },
+ { 3639419 , 105014 },
+ { 3711860 , 105498 },
+ { 3785467 , 105980 },
+ { 3860253 , 106462 },
+ { 3936229 , 106942 },
+ { 4013410 , 107422 },
+ { 4091808 , 107902 },
+ { 4171435 , 108380 },
+ { 4252306 , 108858 },
+ { 4334431 , 109335 },
+ { 4417825 , 109811 },
+ { 4502501 , 110287 },
+ { 4588472 , 110762 },
+ { 4675750 , 111236 },
+ { 4764349 , 111709 },
+ { 4854283 , 112182 },
+ { 4945564 , 112654 },
+ { 5038206 , 113126 },
+ { 5132223 , 113597 },
+ { 5227627 , 114067 },
+ { 5324432 , 114537 },
+ { 5422652 , 115006 },
+ { 5522299 , 115474 },
+ { 5623389 , 115942 },
+ { 5725934 , 116409 },
+ { 5829948 , 116876 },
+ { 5935446 , 117342 },
+ { 6042439 , 117808 },
+ { 6150943 , 118273 },
+ { 6260972 , 118738 },
+ { 6372538 , 119202 },
+ { 6485657 , 119665 },
+ { 6600342 , 120128 },
+ { 6716607 , 120591 },
+ { 6834467 , 121053 },
+ { 6953935 , 121514 },
+ { 7075025 , 121976 },
+ { 7197752 , 122436 },
+ { 7322131 , 122896 },
+ { 7448175 , 123356 },
+ { 7575898 , 123815 },
+ { 7705316 , 124274 },
+ { 7836442 , 124733 },
+ { 7969291 , 125191 },
+ { 8103877 , 125648 },
+ { 8240216 , 126105 },
+ { 8378321 , 126562 },
+ { 8518208 , 127018 },
+ { 8659890 , 127474 },
+ { 8803384 , 127930 },
+ { 8948702 , 128385 },
+ { 9095861 , 128840 },
+ { 9244875 , 129294 },
+ { 9395760 , 129748 },
+ { 9548529 , 130202 },
+ { 9703198 , 130655 },
+ { 9859782 , 131108 },
+ { 10018296 , 131561 },
+ { 10178755 , 132014 },
+ { 10341174 , 132466 },
+ { 10505569 , 132917 },
+ { 10671954 , 133369 },
+ { 10840345 , 133820 },
+ { 11010757 , 134271 },
+ { 11183206 , 134721 },
+ { 11357706 , 135171 },
+ { 11534274 , 135621 },
+ { 11712924 , 136071 },
+ { 11893673 , 136520 },
+ { 12076536 , 136969 },
+ { 12261527 , 137418 },
+ { 12448664 , 137867 },
+ { 12637961 , 138315 },
+ { 12829435 , 138763 },
+ { 13023101 , 139211 },
+ { 13218974 , 139658 },
+ { 13417071 , 140106 },
+ { 13617407 , 140553 },
+ { 13819999 , 140999 },
+ { 14024862 , 141446 },
+ { 14232012 , 141892 },
+ { 14441465 , 142339 },
+ { 14653238 , 142785 },
+ { 14867346 , 143230 },
+ { 15083805 , 143676 },
+ { 15302632 , 144121 },
+ { 15523842 , 144566 },
+ { 15747453 , 145011 },
+ { 15973479 , 145456 },
+ { 16201939 , 145900 },
+ { 16432847 , 146345 },
+ { 16666221 , 146789 },
+ { 16902076 , 147233 },
+ { 17140429 , 147677 },
+ { 17381297 , 148121 },
+ { 17624696 , 148564 },
+ { 17870643 , 149007 },
+ { 18119154 , 149451 },
+ { 18370247 , 149894 },
+ { 18623936 , 150336 },
+ { 18880241 , 150779 },
+ { 19139176 , 151222 },
+ { 19400759 , 151664 },
+ { 19665007 , 152107 },
+ { 19931936 , 152549 },
+ { 20201564 , 152991 },
+ { 20473907 , 153433 },
+ { 20748982 , 153875 },
+ { 21026807 , 154316 },
+ { 21307399 , 154758 },
+ { 21590773 , 155199 },
+ { 21876949 , 155641 },
+ { 22165941 , 156082 },
+ { 22457769 , 156523 },
+ { 22752449 , 156964 },
+ { 23049999 , 157405 },
+ { 23350435 , 157846 },
+ { 23653774 , 158287 },
+ { 23960036 , 158727 },
+ { 24269236 , 159168 },
+ { 24581392 , 159608 },
+ { 24896521 , 160049 },
+ { 25214642 , 160489 },
+ { 25535772 , 160929 },
+ { 25859927 , 161370 },
+ { 26187127 , 161810 },
+ { 26517388 , 162250 },
+ { 26850728 , 162690 },
+ { 27187165 , 163130 },
+ { 27526716 , 163569 },
+ { 27869400 , 164009 },
+ { 28215234 , 164449 },
+ { 28564236 , 164889 },
+ { 28916423 , 165328 },
+ { 29271815 , 165768 },
+ { 29630428 , 166208 },
+ { 29992281 , 166647 },
+ { 30357392 , 167087 },
+ { 30725779 , 167526 },
+ { 31097459 , 167965 },
+ { 31472452 , 168405 },
+ { 31850774 , 168844 },
+ { 32232445 , 169283 },
+ { 32617482 , 169723 },
+ { 33005904 , 170162 },
+ { 33397730 , 170601 },
+ { 33792976 , 171041 },
+ { 34191663 , 171480 },
+ { 34593807 , 171919 },
+ { 34999428 , 172358 },
+ { 35408544 , 172797 },
+ { 35821174 , 173237 },
+ { 36237335 , 173676 },
+ { 36657047 , 174115 },
+ { 37080329 , 174554 },
+ { 37507197 , 174993 },
+ { 37937673 , 175433 },
+ { 38371773 , 175872 },
+ { 38809517 , 176311 },
+ { 39250924 , 176750 },
+ { 39696012 , 177190 },
+ { 40144800 , 177629 },
+ { 40597308 , 178068 },
+ { 41053553 , 178507 },
+ { 41513554 , 178947 },
+ { 41977332 , 179386 },
+ { 42444904 , 179825 },
+ { 42916290 , 180265 },
+ { 43391509 , 180704 },
+ { 43870579 , 181144 },
+ { 44353520 , 181583 },
+ { 44840352 , 182023 },
+ { 45331092 , 182462 },
+ { 45825761 , 182902 },
+ { 46324378 , 183342 },
+ { 46826961 , 183781 },
+ { 47333531 , 184221 },
+ { 47844106 , 184661 },
+ { 48358706 , 185101 },
+ { 48877350 , 185541 },
+ { 49400058 , 185981 },
+ { 49926849 , 186421 },
+ { 50457743 , 186861 },
+ { 50992759 , 187301 },
+ { 51531916 , 187741 },
+ { 52075235 , 188181 },
+ { 52622735 , 188622 },
+ { 53174435 , 189062 },
+ { 53730355 , 189502 },
+ { 54290515 , 189943 },
+ { 54854935 , 190383 },
+ { 55423634 , 190824 },
+ { 55996633 , 191265 },
+ { 56573950 , 191706 },
+ { 57155606 , 192146 },
+ { 57741621 , 192587 },
+ { 58332014 , 193028 },
+ { 58926806 , 193470 },
+ { 59526017 , 193911 },
+ { 60129666 , 194352 },
+ { 60737774 , 194793 },
+ { 61350361 , 195235 },
+ { 61967446 , 195677 },
+ { 62589050 , 196118 },
+ { 63215194 , 196560 },
+ { 63845897 , 197002 },
+ { 64481179 , 197444 },
+ { 65121061 , 197886 },
+ { 65765563 , 198328 },
+ { 66414705 , 198770 },
+ { 67068508 , 199213 },
+ { 67726992 , 199655 },
+ { 68390177 , 200098 },
+ { 69058085 , 200540 },
+ { 69730735 , 200983 },
+ { 70408147 , 201426 },
+ { 71090343 , 201869 },
+ { 71777343 , 202312 },
+ { 72469168 , 202755 },
+ { 73165837 , 203199 },
+ { 73867373 , 203642 },
+ { 74573795 , 204086 },
+ { 75285124 , 204529 },
+ { 76001380 , 204973 },
+ { 76722586 , 205417 },
+ { 77448761 , 205861 },
+ { 78179926 , 206306 },
+ { 78916102 , 206750 },
+ { 79657310 , 207194 },
+ { 80403571 , 207639 },
+ { 81154906 , 208084 },
+ { 81911335 , 208529 },
+ { 82672880 , 208974 },
+ { 83439562 , 209419 },
+ { 84211402 , 209864 },
+ { 84988421 , 210309 },
+ { 85770640 , 210755 },
+ { 86558080 , 211201 },
+ { 87350762 , 211647 },
+ { 88148708 , 212093 },
+ { 88951938 , 212539 },
+ { 89760475 , 212985 },
+ { 90574339 , 213432 },
+ { 91393551 , 213878 },
+ { 92218133 , 214325 },
+ { 93048107 , 214772 },
+ { 93883493 , 215219 },
+ { 94724314 , 215666 },
+ { 95570590 , 216114 },
+ { 96422343 , 216561 },
+ { 97279594 , 217009 },
+ { 98142366 , 217457 },
+ { 99010679 , 217905 },
+ { 99884556 , 218353 },
+ { 100764018 , 218801 },
+ { 101649086 , 219250 },