* Re: 2.6.16-rc4-mm1
From: Adrian Bunk @ 2006-02-20 21:09 UTC (permalink / raw)
To: dccp
In-Reply-To: <43F9CE18.10709@trash.net>
On Mon, Feb 20, 2006 at 05:56:47PM -0300, Arnaldo Carvalho de Melo wrote:
>...
> So perhaps something like what is done for the io schedulers, will study this...
The io schedulers solve this through "always build the noop scheduler"...
> - Arnaldo
cu
Adrian
--
"Is there not promise of rain?" Ling Tan asked suddenly out
of the darkness. There had been need of rain for many days.
"Only a promise," Lao Er said.
Pearl S. Buck - Dragon Seed
^ permalink raw reply
* Re: 2.6.16-rc4-mm1
From: Arnaldo Carvalho de Melo @ 2006-02-20 20:56 UTC (permalink / raw)
To: dccp
In-Reply-To: <43F9CE18.10709@trash.net>
On 2/20/06, Carl-Daniel Hailfinger <c-d.hailfinger.devel.2006@gmx.net> wrote:
> Patrick McHardy schrieb:
> > Reuben Farrelly wrote:
> >
> >>Minor dependency issue:
> >>
> >>My compile failed with this..
> >>
> >> CC [M] net/netfilter/xt_dccp.o
> >>In file included from net/netfilter/xt_dccp.c:15:
> >>include/linux/dccp.h:341:2: error: #error "At least one CCID must be
> >>built as the default"
> >>make[2]: *** [net/netfilter/xt_dccp.o] Error 1
> >>make[1]: *** [net/netfilter] Error 2
> >>make: *** [net] Error 2
> >>[root@tornado linux-2.6-mm]#
> >>
> >>[I have no idea what a CCID is]
> >>
> >>But it was caused by this:
> >>
> >>CONFIG_NETFILTER_XT_MATCH_DCCP=m
> >>
> >>and maybe this below had an impact:
> >>
> >>#
> >># DCCP Configuration (EXPERIMENTAL)
> >>#
> >># CONFIG_IP_DCCP is not set
> >>
> >>After unsetting the option to build the DCCP Netfilter module, I was
> >>able to compile through to completion.
> >
> >
> > Ideally this dependency should be enforced by Kconfig. I'm not sure
> > if it is possible to express something like "IP_DCCP_CCID2 and
> > IP_DCCP_CCID3 depend on DCCP, DCCP requires at least one of both
> > to be enabled". Can someone more familiar with Kconfig than me
> > comment on this? Otherwise the #error should be moved to
> > net/dccp/options.c to keep dccp.h usable without dccp enabled.
>
> Suggestion (not tested):
>
> config IP_DCCP_CCID2
> tristate "blah"
> select DCCP
> help
> Foo
> config IP_DCCP_CCID3
> tristate "blah"
> select DCCP
> help
> Foo
> config DCCP
> bool "blah"
> depends on IP_DCCP_CCID2 || IP_DCCP_CCID3
> help
> Foo
NAK, its more clear to be exposed to DCCP specific stuff such as CCIDs only
if the user selected DCCP.
So perhaps something like what is done for the io schedulers, will study this...
- Arnaldo
^ permalink raw reply
* Re: 2.6.16-rc4-mm1
From: Adrian Bunk @ 2006-02-20 20:44 UTC (permalink / raw)
To: dccp
In-Reply-To: <43F9CE18.10709@trash.net>
On Mon, Feb 20, 2006 at 03:11:36PM +0100, Patrick McHardy wrote:
> Reuben Farrelly wrote:
> > Minor dependency issue:
> >
> > My compile failed with this..
> >
> > CC [M] net/netfilter/xt_dccp.o
> > In file included from net/netfilter/xt_dccp.c:15:
> > include/linux/dccp.h:341:2: error: #error "At least one CCID must be
> > built as the default"
> > make[2]: *** [net/netfilter/xt_dccp.o] Error 1
> > make[1]: *** [net/netfilter] Error 2
> > make: *** [net] Error 2
> > [root@tornado linux-2.6-mm]#
> >
> > [I have no idea what a CCID is]
> >
> > But it was caused by this:
> >
> > CONFIG_NETFILTER_XT_MATCH_DCCP=m
> >
> > and maybe this below had an impact:
> >
> > #
> > # DCCP Configuration (EXPERIMENTAL)
> > #
> > # CONFIG_IP_DCCP is not set
> >
> > After unsetting the option to build the DCCP Netfilter module, I was
> > able to compile through to completion.
>
> Ideally this dependency should be enforced by Kconfig. I'm not sure
> if it is possible to express something like "IP_DCCP_CCID2 and
> IP_DCCP_CCID3 depend on DCCP, DCCP requires at least one of both
> to be enabled". Can someone more familiar with Kconfig than me
> comment on this? Otherwise the #error should be moved to
> net/dccp/options.c to keep dccp.h usable without dccp enabled.
I can try to do it, but I need the exact semantics.
Should all of the following stay allowed configurations?
CONFIG_IP_DCCP=y
CONFIG_IP_DCCP_CCID2=m
CONFIG_IP_DCCP_CCID3=n
CONFIG_IP_DCCP=y
CONFIG_IP_DCCP_CCID2=y
CONFIG_IP_DCCP_CCID3=m
cu
Adrian
--
"Is there not promise of rain?" Ling Tan asked suddenly out
of the darkness. There had been need of rain for many days.
"Only a promise," Lao Er said.
Pearl S. Buck - Dragon Seed
^ permalink raw reply
* Re: 2.6.16-rc4-mm1
From: Carl-Daniel Hailfinger @ 2006-02-20 20:04 UTC (permalink / raw)
To: dccp
In-Reply-To: <43F9CE18.10709@trash.net>
Patrick McHardy schrieb:
> Reuben Farrelly wrote:
>
>>Minor dependency issue:
>>
>>My compile failed with this..
>>
>> CC [M] net/netfilter/xt_dccp.o
>>In file included from net/netfilter/xt_dccp.c:15:
>>include/linux/dccp.h:341:2: error: #error "At least one CCID must be
>>built as the default"
>>make[2]: *** [net/netfilter/xt_dccp.o] Error 1
>>make[1]: *** [net/netfilter] Error 2
>>make: *** [net] Error 2
>>[root@tornado linux-2.6-mm]#
>>
>>[I have no idea what a CCID is]
>>
>>But it was caused by this:
>>
>>CONFIG_NETFILTER_XT_MATCH_DCCP=m
>>
>>and maybe this below had an impact:
>>
>>#
>># DCCP Configuration (EXPERIMENTAL)
>>#
>># CONFIG_IP_DCCP is not set
>>
>>After unsetting the option to build the DCCP Netfilter module, I was
>>able to compile through to completion.
>
>
> Ideally this dependency should be enforced by Kconfig. I'm not sure
> if it is possible to express something like "IP_DCCP_CCID2 and
> IP_DCCP_CCID3 depend on DCCP, DCCP requires at least one of both
> to be enabled". Can someone more familiar with Kconfig than me
> comment on this? Otherwise the #error should be moved to
> net/dccp/options.c to keep dccp.h usable without dccp enabled.
Suggestion (not tested):
config IP_DCCP_CCID2
tristate "blah"
select DCCP
help
Foo
config IP_DCCP_CCID3
tristate "blah"
select DCCP
help
Foo
config DCCP
bool "blah"
depends on IP_DCCP_CCID2 || IP_DCCP_CCID3
help
Foo
Regards,
Carl-Daniel
--
http://www.hailfinger.org/
^ permalink raw reply
* Re: 2.6.16-rc4-mm1
From: Arnaldo Carvalho de Melo @ 2006-02-20 14:20 UTC (permalink / raw)
To: dccp
In-Reply-To: <43F9CE18.10709@trash.net>
On 2/20/06, Patrick McHardy <kaber@trash.net> wrote:
> Reuben Farrelly wrote:
> > Minor dependency issue:
> >
> > My compile failed with this..
> >
> > CC [M] net/netfilter/xt_dccp.o
> > In file included from net/netfilter/xt_dccp.c:15:
> > include/linux/dccp.h:341:2: error: #error "At least one CCID must be
> > built as the default"
> > make[2]: *** [net/netfilter/xt_dccp.o] Error 1
> > make[1]: *** [net/netfilter] Error 2
> > make: *** [net] Error 2
> > [root@tornado linux-2.6-mm]#
> >
> > [I have no idea what a CCID is]
> >
> > But it was caused by this:
> >
> > CONFIG_NETFILTER_XT_MATCH_DCCP=m
> >
> > and maybe this below had an impact:
> >
> > #
> > # DCCP Configuration (EXPERIMENTAL)
> > #
> > # CONFIG_IP_DCCP is not set
> >
> > After unsetting the option to build the DCCP Netfilter module, I was
> > able to compile through to completion.
>
> Ideally this dependency should be enforced by Kconfig. I'm not sure
> if it is possible to express something like "IP_DCCP_CCID2 and
> IP_DCCP_CCID3 depend on DCCP, DCCP requires at least one of both
> to be enabled". Can someone more familiar with Kconfig than me
> comment on this? Otherwise the #error should be moved to
> net/dccp/options.c to keep dccp.h usable without dccp enabled.
oops, I think I'll move the #error to options.c, thanks for forwarding
this report
to dccp@vger.kernel.org.
- Arnaldo
^ permalink raw reply
* Re: 2.6.16-rc4-mm1
From: Patrick McHardy @ 2006-02-20 14:11 UTC (permalink / raw)
To: dccp
Reuben Farrelly wrote:
> Minor dependency issue:
>
> My compile failed with this..
>
> CC [M] net/netfilter/xt_dccp.o
> In file included from net/netfilter/xt_dccp.c:15:
> include/linux/dccp.h:341:2: error: #error "At least one CCID must be
> built as the default"
> make[2]: *** [net/netfilter/xt_dccp.o] Error 1
> make[1]: *** [net/netfilter] Error 2
> make: *** [net] Error 2
> [root@tornado linux-2.6-mm]#
>
> [I have no idea what a CCID is]
>
> But it was caused by this:
>
> CONFIG_NETFILTER_XT_MATCH_DCCP=m
>
> and maybe this below had an impact:
>
> #
> # DCCP Configuration (EXPERIMENTAL)
> #
> # CONFIG_IP_DCCP is not set
>
> After unsetting the option to build the DCCP Netfilter module, I was
> able to compile through to completion.
Ideally this dependency should be enforced by Kconfig. I'm not sure
if it is possible to express something like "IP_DCCP_CCID2 and
IP_DCCP_CCID3 depend on DCCP, DCCP requires at least one of both
to be enabled". Can someone more familiar with Kconfig than me
comment on this? Otherwise the #error should be moved to
net/dccp/options.c to keep dccp.h usable without dccp enabled.
^ permalink raw reply
* [PATCH 2/2][DCCP] feat: Actually change the CCID upon negotiation
From: Arnaldo Carvalho de Melo @ 2006-02-20 12:43 UTC (permalink / raw)
To: dccp
[-- Attachment #1: Type: text/plain, Size: 226 bytes --]
Hi David,
Please consider pulling from the "dccp_upstream" branch of:
master.kernel.org:/pub/scm/linux/kernel/git/acme/net-2.6.17.git
Now there are two outstanding csets in this tree.
Best Regards,
- Arnaldo
[-- Attachment #2: 2.patch --]
[-- Type: text/x-patch, Size: 2735 bytes --]
tree 4ec67bef992ff59201add0d15e0e2be7c259d810
parent dd44614e443c8cb99187b26f4b82742d0f0aead2
author Andrea Bittau <a.bittau@cs.ucl.ac.uk> 1140438471 -0300
committer Arnaldo Carvalho de Melo <acme@mandriva.com> 1140438471 -0300
[DCCP] feat: Actually change the CCID upon negotiation
Change the CCID upon successful feature negotiation.
Commiter note: patch mostly rewritten to use the new ccid API.
Signed-off-by: Andrea Bittau <a.bittau@cs.ucl.ac.uk>
Signed-off-by: Arnaldo Carvalho de Melo <acme@mandriva.com>
------------------------------------------------------------------------------
feat.c | 43 ++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 42 insertions(+), 1 deletion(-)
------------------------------------------------------------------------------
diff --git a/net/dccp/feat.c b/net/dccp/feat.c
index fb74260..0ab5f84 100644
--- a/net/dccp/feat.c
+++ b/net/dccp/feat.c
@@ -14,6 +14,7 @@
#include <linux/module.h>
#include "dccp.h"
+#include "ccid.h"
#include "feat.h"
#define DCCP_FEAT_SP_NOAGREE (-123)
@@ -26,6 +27,8 @@ int dccp_feat_change(struct sock *sk, u8
dccp_pr_debug("feat change type=%d feat=%d\n", type, feature);
+ /* XXX sanity check feat change request */
+
/* check if that feature is already being negotiated */
list_for_each_entry(opt, &dp->dccps_options.dccpo_pending,
dccpop_node) {
@@ -62,11 +65,49 @@ int dccp_feat_change(struct sock *sk, u8
EXPORT_SYMBOL_GPL(dccp_feat_change);
+static int dccp_feat_update_ccid(struct sock *sk, u8 type, u8 new_ccid_nr)
+{
+ struct dccp_sock *dp = dccp_sk(sk);
+ /* figure out if we are changing our CCID or the peer's */
+ const int rx = type == DCCPO_CHANGE_R;
+ const u8 ccid_nr = rx ? dp->dccps_options.dccpo_rx_ccid :
+ dp->dccps_options.dccpo_tx_ccid;
+ struct ccid *new_ccid;
+
+ /* Check if nothing is being changed. */
+ if (ccid_nr == new_ccid_nr)
+ return 0;
+
+ new_ccid = ccid_new(new_ccid_nr, sk, rx, GFP_ATOMIC);
+ if (new_ccid == NULL)
+ return -ENOMEM;
+
+ if (rx) {
+ ccid_hc_rx_delete(dp->dccps_hc_rx_ccid, sk);
+ dp->dccps_hc_rx_ccid = new_ccid;
+ dp->dccps_options.dccpo_rx_ccid = new_ccid_nr;
+ } else {
+ ccid_hc_tx_delete(dp->dccps_hc_tx_ccid, sk);
+ dp->dccps_hc_tx_ccid = new_ccid;
+ dp->dccps_options.dccpo_tx_ccid = new_ccid_nr;
+ }
+
+ return 0;
+}
+
/* XXX taking only u8 vals */
static int dccp_feat_update(struct sock *sk, u8 type, u8 feat, u8 val)
{
- /* FIXME implement */
dccp_pr_debug("changing [%d] feat %d to %d\n", type, feat, val);
+
+ switch (feat) {
+ case DCCPF_CCID:
+ return dccp_feat_update_ccid(sk, type, val);
+ default:
+ dccp_pr_debug("IMPLEMENT changing [%d] feat %d to %d\n",
+ type, feat, val);
+ break;
+ }
return 0;
}
^ permalink raw reply related
* Re: [PATCH 1/2][DCCP] CCID: Improve CCID infrastructure
From: Arnaldo Carvalho de Melo @ 2006-02-20 12:42 UTC (permalink / raw)
To: dccp
In-Reply-To: <39e6f6c70602200441m797c130eg7baa62b7c344c240@mail.gmail.com>
Oops,
Sorry David, please pull from the "dccp_upstream" branch.
- Arnaldo
On 2/20/06, Arnaldo Carvalho de Melo <acme@ghostprotocols.net> wrote:
> Hi David,
>
> Please consider pulling from:
>
> master.kernel.org:/pub/scm/linux/kernel/git/acme/net-2.6.17.git
>
> Now there are two outstanding csets in this tree.
>
> Best Regards,
>
> - Arnaldo
>
>
>
^ permalink raw reply
* [PATCH 1/2][DCCP] CCID: Improve CCID infrastructure
From: Arnaldo Carvalho de Melo @ 2006-02-20 12:41 UTC (permalink / raw)
To: dccp
[-- Attachment #1: Type: text/plain, Size: 196 bytes --]
Hi David,
Please consider pulling from:
master.kernel.org:/pub/scm/linux/kernel/git/acme/net-2.6.17.git
Now there are two outstanding csets in this tree.
Best Regards,
- Arnaldo
[-- Attachment #2: 1.patch --]
[-- Type: text/x-patch, Size: 27931 bytes --]
tree 311a5fb90764c6e7a57dc8b17460bea2d3efc65c
parent 53986ff2e7e5e087f62847882ae1f4516449c414
author Arnaldo Carvalho de Melo <acme@mandriva.com> 1140438322 -0300
committer Arnaldo Carvalho de Melo <acme@mandriva.com> 1140438322 -0300
[DCCP] CCID: Improve CCID infrastructure
1. No need for ->ccid_init nor ->ccid_exit, this is what module_{init,exit}
does and anynways neither ccid2 nor ccid3 were using it.
2. Rename struct ccid to struct ccid_operations and introduce struct ccid
with a pointer to ccid_operations and rigth after it the rx or tx
private state.
3. Remove the pointer to the state of the half connections from struct
dccp_sock, now its derived thru ccid_priv() from the ccid pointer.
Now we also can implement the setsockopt for changing the CCID easily as
no ccid init routines can affect struct dccp_sock in any way that prevents
other CCIDs from working if a CCID switch operation is asked by apps.
Signed-off-by: Arnaldo Carvalho de Melo <acme@mandriva.com>
------------------------------------------------------------------------------
include/linux/dccp.h | 2
net/dccp/ccid.c | 188 ++++++++++++++++++++++++++++++++++++++++---------
net/dccp/ccid.h | 117 +++++++++++++-----------------
net/dccp/ccids/ccid2.c | 55 ++------------
net/dccp/ccids/ccid2.h | 16 ++++
net/dccp/ccids/ccid3.c | 34 +-------
net/dccp/ccids/ccid3.h | 5 -
net/dccp/input.c | 8 --
net/dccp/ipv4.c | 24 +++---
net/dccp/minisocks.c | 25 ++----
10 files changed, 261 insertions(+), 213 deletions(-)
------------------------------------------------------------------------------
diff --git a/include/linux/dccp.h b/include/linux/dccp.h
index a70d1a2..bdd756c 100644
--- a/include/linux/dccp.h
+++ b/include/linux/dccp.h
@@ -478,8 +478,6 @@ struct dccp_sock {
__u32 dccps_mss_cache;
struct dccp_options dccps_options;
struct dccp_ackvec *dccps_hc_rx_ackvec;
- void *dccps_hc_rx_ccid_private;
- void *dccps_hc_tx_ccid_private;
struct ccid *dccps_hc_rx_ccid;
struct ccid *dccps_hc_tx_ccid;
struct dccp_options_received dccps_options_received;
diff --git a/net/dccp/ccid.c b/net/dccp/ccid.c
index 06b191a..b6f6251 100644
--- a/net/dccp/ccid.c
+++ b/net/dccp/ccid.c
@@ -13,7 +13,7 @@
#include "ccid.h"
-static struct ccid *ccids[CCID_MAX];
+static struct ccid_operations *ccids[CCID_MAX];
#if defined(CONFIG_SMP) || defined(CONFIG_PREEMPT)
static atomic_t ccids_lockct = ATOMIC_INIT(0);
static DEFINE_SPINLOCK(ccids_lock);
@@ -55,82 +55,202 @@ static inline void ccids_read_unlock(voi
#define ccids_read_unlock() do { } while(0)
#endif
-int ccid_register(struct ccid *ccid)
+static kmem_cache_t *ccid_kmem_cache_create(int obj_size, const char *fmt,...)
{
- int err;
+ kmem_cache_t *slab;
+ char slab_name_fmt[32], *slab_name;
+ va_list args;
+
+ va_start(args, fmt);
+ vsnprintf(slab_name_fmt, sizeof(slab_name_fmt), fmt, args);
+ va_end(args);
+
+ slab_name = kstrdup(slab_name_fmt, GFP_KERNEL);
+ if (slab_name == NULL)
+ return NULL;
+ slab = kmem_cache_create(slab_name, sizeof(struct ccid) + obj_size, 0,
+ SLAB_HWCACHE_ALIGN, NULL, NULL);
+ if (slab == NULL)
+ kfree(slab_name);
+ return slab;
+}
+
+static void ccid_kmem_cache_destroy(kmem_cache_t *slab)
+{
+ if (slab != NULL) {
+ const char *name = kmem_cache_name(slab);
+
+ kmem_cache_destroy(slab);
+ kfree(name);
+ }
+}
+
+int ccid_register(struct ccid_operations *ccid_ops)
+{
+ int err = -ENOBUFS;
+
+ ccid_ops->ccid_hc_rx_slab =
+ ccid_kmem_cache_create(ccid_ops->ccid_hc_rx_obj_size,
+ "%s_hc_rx_sock",
+ ccid_ops->ccid_name);
+ if (ccid_ops->ccid_hc_rx_slab == NULL)
+ goto out;
+
+ ccid_ops->ccid_hc_tx_slab =
+ ccid_kmem_cache_create(ccid_ops->ccid_hc_tx_obj_size,
+ "%s_hc_tx_sock",
+ ccid_ops->ccid_name);
+ if (ccid_ops->ccid_hc_tx_slab == NULL)
+ goto out_free_rx_slab;
ccids_write_lock();
err = -EEXIST;
- if (ccids[ccid->ccid_id] == NULL) {
- ccids[ccid->ccid_id] = ccid;
+ if (ccids[ccid_ops->ccid_id] == NULL) {
+ ccids[ccid_ops->ccid_id] = ccid_ops;
err = 0;
}
ccids_write_unlock();
- if (err == 0)
- pr_info("CCID: Registered CCID %d (%s)\n",
- ccid->ccid_id, ccid->ccid_name);
+ if (err != 0)
+ goto out_free_tx_slab;
+
+ pr_info("CCID: Registered CCID %d (%s)\n",
+ ccid_ops->ccid_id, ccid_ops->ccid_name);
+out:
return err;
+out_free_tx_slab:
+ ccid_kmem_cache_destroy(ccid_ops->ccid_hc_tx_slab);
+ ccid_ops->ccid_hc_tx_slab = NULL;
+ goto out;
+out_free_rx_slab:
+ ccid_kmem_cache_destroy(ccid_ops->ccid_hc_rx_slab);
+ ccid_ops->ccid_hc_rx_slab = NULL;
+ goto out;
}
EXPORT_SYMBOL_GPL(ccid_register);
-int ccid_unregister(struct ccid *ccid)
+int ccid_unregister(struct ccid_operations *ccid_ops)
{
ccids_write_lock();
- ccids[ccid->ccid_id] = NULL;
+ ccids[ccid_ops->ccid_id] = NULL;
ccids_write_unlock();
+
+ ccid_kmem_cache_destroy(ccid_ops->ccid_hc_tx_slab);
+ ccid_ops->ccid_hc_tx_slab = NULL;
+ ccid_kmem_cache_destroy(ccid_ops->ccid_hc_rx_slab);
+ ccid_ops->ccid_hc_rx_slab = NULL;
+
pr_info("CCID: Unregistered CCID %d (%s)\n",
- ccid->ccid_id, ccid->ccid_name);
+ ccid_ops->ccid_id, ccid_ops->ccid_name);
return 0;
}
EXPORT_SYMBOL_GPL(ccid_unregister);
-struct ccid *ccid_init(unsigned char id, struct sock *sk)
+struct ccid *ccid_new(unsigned char id, struct sock *sk, int rx, gfp_t gfp)
{
- struct ccid *ccid;
+ struct ccid_operations *ccid_ops;
+ struct ccid *ccid = NULL;
+ ccids_read_lock();
#ifdef CONFIG_KMOD
- if (ccids[id] == NULL)
+ if (ccids[id] == NULL) {
+ /* We only try to load if in process context */
+ ccids_read_unlock();
+ if (gfp & GFP_ATOMIC)
+ goto out;
request_module("net-dccp-ccid-%d", id);
+ ccids_read_lock();
+ }
#endif
- ccids_read_lock();
+ ccid_ops = ccids[id];
+ if (ccid_ops == NULL)
+ goto out_unlock;
- ccid = ccids[id];
- if (ccid == NULL)
- goto out;
+ if (!try_module_get(ccid_ops->ccid_owner))
+ goto out_unlock;
- if (!try_module_get(ccid->ccid_owner))
- goto out_err;
+ ccids_read_unlock();
- if (ccid->ccid_init != NULL && ccid->ccid_init(sk) != 0)
+ ccid = kmem_cache_alloc(rx ? ccid_ops->ccid_hc_rx_slab :
+ ccid_ops->ccid_hc_tx_slab, gfp);
+ if (ccid == NULL)
goto out_module_put;
+ ccid->ccid_ops = ccid_ops;
+ if (rx) {
+ memset(ccid + 1, 0, ccid_ops->ccid_hc_rx_obj_size);
+ if (ccid->ccid_ops->ccid_hc_rx_init != NULL &&
+ ccid->ccid_ops->ccid_hc_rx_init(ccid, sk) != 0)
+ goto out_free_ccid;
+ } else {
+ memset(ccid + 1, 0, ccid_ops->ccid_hc_tx_obj_size);
+ if (ccid->ccid_ops->ccid_hc_tx_init != NULL &&
+ ccid->ccid_ops->ccid_hc_tx_init(ccid, sk) != 0)
+ goto out_free_ccid;
+ }
out:
- ccids_read_unlock();
return ccid;
-out_module_put:
- module_put(ccid->ccid_owner);
-out_err:
+out_unlock:
+ ccids_read_unlock();
+ goto out;
+out_free_ccid:
+ kmem_cache_free(rx ? ccid_ops->ccid_hc_rx_slab :
+ ccid_ops->ccid_hc_tx_slab, ccid);
ccid = NULL;
+out_module_put:
+ module_put(ccid_ops->ccid_owner);
goto out;
}
-EXPORT_SYMBOL_GPL(ccid_init);
+EXPORT_SYMBOL_GPL(ccid_new);
+
+struct ccid *ccid_hc_rx_new(unsigned char id, struct sock *sk, gfp_t gfp)
+{
+ return ccid_new(id, sk, 1, gfp);
+}
+
+EXPORT_SYMBOL_GPL(ccid_hc_rx_new);
+
+struct ccid *ccid_hc_tx_new(unsigned char id,struct sock *sk, gfp_t gfp)
+{
+ return ccid_new(id, sk, 0, gfp);
+}
+
+EXPORT_SYMBOL_GPL(ccid_hc_tx_new);
-void ccid_exit(struct ccid *ccid, struct sock *sk)
+static void ccid_delete(struct ccid *ccid, struct sock *sk, int rx)
{
+ struct ccid_operations *ccid_ops;
+
if (ccid == NULL)
return;
+ ccid_ops = ccid->ccid_ops;
+ if (rx) {
+ if (ccid_ops->ccid_hc_rx_exit != NULL)
+ ccid_ops->ccid_hc_rx_exit(sk);
+ kmem_cache_free(ccid_ops->ccid_hc_rx_slab, ccid);
+ } else {
+ if (ccid_ops->ccid_hc_tx_exit != NULL)
+ ccid_ops->ccid_hc_tx_exit(sk);
+ kmem_cache_free(ccid_ops->ccid_hc_tx_slab, ccid);
+ }
ccids_read_lock();
+ if (ccids[ccid_ops->ccid_id] != NULL)
+ module_put(ccid_ops->ccid_owner);
+ ccids_read_unlock();
+}
- if (ccids[ccid->ccid_id] != NULL) {
- if (ccid->ccid_exit != NULL)
- ccid->ccid_exit(sk);
- module_put(ccid->ccid_owner);
- }
+void ccid_hc_rx_delete(struct ccid *ccid, struct sock *sk)
+{
+ ccid_delete(ccid, sk, 1);
+}
- ccids_read_unlock();
+EXPORT_SYMBOL_GPL(ccid_hc_rx_delete);
+
+void ccid_hc_tx_delete(struct ccid *ccid, struct sock *sk)
+{
+ ccid_delete(ccid, sk, 0);
}
-EXPORT_SYMBOL_GPL(ccid_exit);
+EXPORT_SYMBOL_GPL(ccid_hc_tx_delete);
diff --git a/net/dccp/ccid.h b/net/dccp/ccid.h
index de681c6..3199f07 100644
--- a/net/dccp/ccid.h
+++ b/net/dccp/ccid.h
@@ -23,14 +23,16 @@
struct tcp_info;
-struct ccid {
+struct ccid_operations {
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);
+ kmem_cache_t *ccid_hc_rx_slab;
+ __u32 ccid_hc_rx_obj_size;
+ kmem_cache_t *ccid_hc_tx_slab;
+ __u32 ccid_hc_tx_obj_size;
+ int (*ccid_hc_rx_init)(struct ccid *ccid, struct sock *sk);
+ int (*ccid_hc_tx_init)(struct ccid *ccid, 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,
@@ -67,75 +69,58 @@ struct ccid {
int __user *optlen);
};
-extern int ccid_register(struct ccid *ccid);
-extern int ccid_unregister(struct ccid *ccid);
+extern int ccid_register(struct ccid_operations *ccid_ops);
+extern int ccid_unregister(struct ccid_operations *ccid_ops);
-extern struct ccid *ccid_init(unsigned char id, struct sock *sk);
-extern void ccid_exit(struct ccid *ccid, struct sock *sk);
+struct ccid {
+ struct ccid_operations *ccid_ops;
+ char ccid_priv[0];
+};
-static inline void __ccid_get(struct ccid *ccid)
+static inline void *ccid_priv(const struct ccid *ccid)
{
- __module_get(ccid->ccid_owner);
+ return (void *)ccid->ccid_priv;
}
+extern struct ccid *ccid_new(unsigned char id, struct sock *sk, int rx,
+ gfp_t gfp);
+
+extern struct ccid *ccid_hc_rx_new(unsigned char id, struct sock *sk,
+ gfp_t gfp);
+extern struct ccid *ccid_hc_tx_new(unsigned char id, struct sock *sk,
+ gfp_t gfp);
+
+extern void ccid_hc_rx_delete(struct ccid *ccid, struct sock *sk);
+extern void ccid_hc_tx_delete(struct ccid *ccid, struct sock *sk);
+
static inline int ccid_hc_tx_send_packet(struct ccid *ccid, struct sock *sk,
struct sk_buff *skb, int len)
{
int rc = 0;
- if (ccid->ccid_hc_tx_send_packet != NULL)
- rc = ccid->ccid_hc_tx_send_packet(sk, skb, len);
+ if (ccid->ccid_ops->ccid_hc_tx_send_packet != NULL)
+ rc = ccid->ccid_ops->ccid_hc_tx_send_packet(sk, skb, len);
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);
+ if (ccid->ccid_ops->ccid_hc_tx_packet_sent != NULL)
+ ccid->ccid_ops->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 != NULL && ccid->ccid_hc_rx_exit != NULL &&
- dccp_sk(sk)->dccps_hc_rx_ccid_private != NULL)
- ccid->ccid_hc_rx_exit(sk);
-}
-
-static inline void ccid_hc_tx_exit(struct ccid *ccid, struct sock *sk)
-{
- if (ccid != NULL && ccid->ccid_hc_tx_exit != NULL &&
- dccp_sk(sk)->dccps_hc_tx_ccid_private != 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);
+ if (ccid->ccid_ops->ccid_hc_rx_packet_recv != NULL)
+ ccid->ccid_ops->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);
+ if (ccid->ccid_ops->ccid_hc_tx_packet_recv != NULL)
+ ccid->ccid_ops->ccid_hc_tx_packet_recv(sk, skb);
}
static inline int ccid_hc_tx_parse_options(struct ccid *ccid, struct sock *sk,
@@ -144,8 +129,8 @@ static inline int ccid_hc_tx_parse_optio
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,
+ if (ccid->ccid_ops->ccid_hc_tx_parse_options != NULL)
+ rc = ccid->ccid_ops->ccid_hc_tx_parse_options(sk, option, len, idx,
value);
return rc;
}
@@ -156,37 +141,37 @@ static inline int ccid_hc_rx_parse_optio
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);
+ if (ccid->ccid_ops->ccid_hc_rx_parse_options != NULL)
+ rc = ccid->ccid_ops->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);
+ if (ccid->ccid_ops->ccid_hc_tx_insert_options != NULL)
+ ccid->ccid_ops->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);
+ if (ccid->ccid_ops->ccid_hc_rx_insert_options != NULL)
+ ccid->ccid_ops->ccid_hc_rx_insert_options(sk, skb);
}
static inline void ccid_hc_rx_get_info(struct ccid *ccid, struct sock *sk,
struct tcp_info *info)
{
- if (ccid->ccid_hc_rx_get_info != NULL)
- ccid->ccid_hc_rx_get_info(sk, info);
+ if (ccid->ccid_ops->ccid_hc_rx_get_info != NULL)
+ ccid->ccid_ops->ccid_hc_rx_get_info(sk, info);
}
static inline void ccid_hc_tx_get_info(struct ccid *ccid, struct sock *sk,
struct tcp_info *info)
{
- if (ccid->ccid_hc_tx_get_info != NULL)
- ccid->ccid_hc_tx_get_info(sk, info);
+ if (ccid->ccid_ops->ccid_hc_tx_get_info != NULL)
+ ccid->ccid_ops->ccid_hc_tx_get_info(sk, info);
}
static inline int ccid_hc_rx_getsockopt(struct ccid *ccid, struct sock *sk,
@@ -194,8 +179,8 @@ static inline int ccid_hc_rx_getsockopt(
u32 __user *optval, int __user *optlen)
{
int rc = -ENOPROTOOPT;
- if (ccid->ccid_hc_rx_getsockopt != NULL)
- rc = ccid->ccid_hc_rx_getsockopt(sk, optname, len,
+ if (ccid->ccid_ops->ccid_hc_rx_getsockopt != NULL)
+ rc = ccid->ccid_ops->ccid_hc_rx_getsockopt(sk, optname, len,
optval, optlen);
return rc;
}
@@ -205,8 +190,8 @@ static inline int ccid_hc_tx_getsockopt(
u32 __user *optval, int __user *optlen)
{
int rc = -ENOPROTOOPT;
- if (ccid->ccid_hc_tx_getsockopt != NULL)
- rc = ccid->ccid_hc_tx_getsockopt(sk, optname, len,
+ if (ccid->ccid_ops->ccid_hc_tx_getsockopt != NULL)
+ rc = ccid->ccid_ops->ccid_hc_tx_getsockopt(sk, optname, len,
optval, optlen);
return rc;
}
diff --git a/net/dccp/ccids/ccid2.c b/net/dccp/ccids/ccid2.c
index 6d4cb43..11c73ab 100644
--- a/net/dccp/ccids/ccid2.c
+++ b/net/dccp/ccids/ccid2.c
@@ -52,16 +52,6 @@ static int ccid2_debug;
static const int ccid2_seq_len = 128;
-static inline struct ccid2_hc_tx_sock *ccid2_hc_tx_sk(const struct sock *sk)
-{
- return dccp_sk(sk)->dccps_hc_tx_ccid_private;
-}
-
-static inline struct ccid2_hc_rx_sock *ccid2_hc_rx_sk(const struct sock *sk)
-{
- return dccp_sk(sk)->dccps_hc_rx_ccid_private;
-}
-
#ifdef CCID2_DEBUG
static void ccid2_hc_tx_check_sanity(const struct ccid2_hc_tx_sock *hctx)
{
@@ -707,19 +697,12 @@ static void ccid2_hc_tx_packet_recv(stru
ccid2_hc_tx_check_sanity(hctx);
}
-static int ccid2_hc_tx_init(struct sock *sk)
+static int ccid2_hc_tx_init(struct ccid *ccid, struct sock *sk)
{
- struct dccp_sock *dp = dccp_sk(sk);
- struct ccid2_hc_tx_sock *hctx;
+ struct ccid2_hc_tx_sock *hctx = ccid_priv(ccid);
int seqcount = ccid2_seq_len;
int i;
- dp->dccps_hc_tx_ccid_private = kzalloc(sizeof(*hctx), gfp_any());
- if (dp->dccps_hc_tx_ccid_private == NULL)
- return -ENOMEM;
-
- hctx = ccid2_hc_tx_sk(sk);
-
/* XXX init variables with proper values */
hctx->ccid2hctx_cwnd = 1;
hctx->ccid2hctx_ssthresh = 10;
@@ -728,11 +711,9 @@ static int ccid2_hc_tx_init(struct sock
/* XXX init ~ to window size... */
hctx->ccid2hctx_seqbuf = kmalloc(sizeof(*hctx->ccid2hctx_seqbuf) *
seqcount, gfp_any());
- if (hctx->ccid2hctx_seqbuf == NULL) {
- kfree(dp->dccps_hc_tx_ccid_private);
- dp->dccps_hc_tx_ccid_private = NULL;
+ if (hctx->ccid2hctx_seqbuf == NULL)
return -ENOMEM;
- }
+
for (i = 0; i < (seqcount - 1); i++) {
hctx->ccid2hctx_seqbuf[i].ccid2s_next =
&hctx->ccid2hctx_seqbuf[i + 1];
@@ -763,15 +744,11 @@ static int ccid2_hc_tx_init(struct sock
static void ccid2_hc_tx_exit(struct sock *sk)
{
- struct dccp_sock *dp = dccp_sk(sk);
struct ccid2_hc_tx_sock *hctx = ccid2_hc_tx_sk(sk);
ccid2_hc_tx_kill_rto_timer(sk);
-
kfree(hctx->ccid2hctx_seqbuf);
-
- kfree(dp->dccps_hc_tx_ccid_private);
- dp->dccps_hc_tx_ccid_private = NULL;
+ hctx->ccid2hctx_seqbuf = NULL;
}
static void ccid2_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb)
@@ -791,33 +768,17 @@ static void ccid2_hc_rx_packet_recv(stru
}
}
-static int ccid2_hc_rx_init(struct sock *sk)
-{
- struct dccp_sock *dp = dccp_sk(sk);
- dp->dccps_hc_rx_ccid_private = kzalloc(sizeof(struct ccid2_hc_rx_sock),
- gfp_any());
- return dp->dccps_hc_rx_ccid_private == NULL ? -ENOMEM : 0;
-}
-
-static void ccid2_hc_rx_exit(struct sock *sk)
-{
- struct dccp_sock *dp = dccp_sk(sk);
-
- kfree(dp->dccps_hc_rx_ccid_private);
- dp->dccps_hc_rx_ccid_private = NULL;
-}
-
-static struct ccid ccid2 = {
+static struct ccid_operations ccid2 = {
.ccid_id = 2,
.ccid_name = "ccid2",
.ccid_owner = THIS_MODULE,
+ .ccid_hc_tx_obj_size = sizeof(struct ccid2_hc_tx_sock),
.ccid_hc_tx_init = ccid2_hc_tx_init,
.ccid_hc_tx_exit = ccid2_hc_tx_exit,
.ccid_hc_tx_send_packet = ccid2_hc_tx_send_packet,
.ccid_hc_tx_packet_sent = ccid2_hc_tx_packet_sent,
.ccid_hc_tx_packet_recv = ccid2_hc_tx_packet_recv,
- .ccid_hc_rx_init = ccid2_hc_rx_init,
- .ccid_hc_rx_exit = ccid2_hc_rx_exit,
+ .ccid_hc_rx_obj_size = sizeof(struct ccid2_hc_rx_sock),
.ccid_hc_rx_packet_recv = ccid2_hc_rx_packet_recv,
};
diff --git a/net/dccp/ccids/ccid2.h b/net/dccp/ccids/ccid2.h
index 0b08c90..451a874 100644
--- a/net/dccp/ccids/ccid2.h
+++ b/net/dccp/ccids/ccid2.h
@@ -20,6 +20,13 @@
#ifndef _DCCP_CCID2_H_
#define _DCCP_CCID2_H_
+#include <linux/dccp.h>
+#include <linux/timer.h>
+#include <linux/types.h>
+#include "../ccid.h"
+
+struct sock;
+
struct ccid2_seq {
u64 ccid2s_seq;
unsigned long ccid2s_sent;
@@ -66,4 +73,13 @@ struct ccid2_hc_rx_sock {
int ccid2hcrx_data;
};
+static inline struct ccid2_hc_tx_sock *ccid2_hc_tx_sk(const struct sock *sk)
+{
+ return ccid_priv(dccp_sk(sk)->dccps_hc_tx_ccid);
+}
+
+static inline struct ccid2_hc_rx_sock *ccid2_hc_rx_sk(const struct sock *sk)
+{
+ return ccid_priv(dccp_sk(sk)->dccps_hc_rx_ccid);
+}
#endif /* _DCCP_CCID2_H_ */
diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c
index 165fc40..a357c15 100644
--- a/net/dccp/ccids/ccid3.c
+++ b/net/dccp/ccids/ccid3.c
@@ -647,17 +647,10 @@ static int ccid3_hc_tx_parse_options(str
return rc;
}
-static int ccid3_hc_tx_init(struct sock *sk)
+static int ccid3_hc_tx_init(struct ccid *ccid, struct sock *sk)
{
struct dccp_sock *dp = dccp_sk(sk);
- struct ccid3_hc_tx_sock *hctx;
-
- dp->dccps_hc_tx_ccid_private = kmalloc(sizeof(*hctx), gfp_any());
- if (dp->dccps_hc_tx_ccid_private == NULL)
- return -ENOMEM;
-
- hctx = ccid3_hc_tx_sk(sk);
- memset(hctx, 0, sizeof(*hctx));
+ struct ccid3_hc_tx_sock *hctx = ccid_priv(ccid);
if (dp->dccps_packet_size >= TFRC_MIN_PACKET_SIZE &&
dp->dccps_packet_size <= TFRC_MAX_PACKET_SIZE)
@@ -680,7 +673,6 @@ static int ccid3_hc_tx_init(struct sock
static void ccid3_hc_tx_exit(struct sock *sk)
{
- struct dccp_sock *dp = dccp_sk(sk);
struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);
BUG_ON(hctx == NULL);
@@ -690,9 +682,6 @@ static void ccid3_hc_tx_exit(struct sock
/* Empty packet history */
dccp_tx_hist_purge(ccid3_tx_hist, &hctx->ccid3hctx_hist);
-
- kfree(dp->dccps_hc_tx_ccid_private);
- dp->dccps_hc_tx_ccid_private = NULL;
}
/*
@@ -1035,20 +1024,13 @@ static void ccid3_hc_rx_packet_recv(stru
}
}
-static int ccid3_hc_rx_init(struct sock *sk)
+static int ccid3_hc_rx_init(struct ccid *ccid, struct sock *sk)
{
struct dccp_sock *dp = dccp_sk(sk);
- struct ccid3_hc_rx_sock *hcrx;
+ struct ccid3_hc_rx_sock *hcrx = ccid_priv(ccid);
ccid3_pr_debug("%s, sk=%p\n", dccp_role(sk), sk);
- dp->dccps_hc_rx_ccid_private = kmalloc(sizeof(*hcrx), gfp_any());
- if (dp->dccps_hc_rx_ccid_private == NULL)
- return -ENOMEM;
-
- hcrx = ccid3_hc_rx_sk(sk);
- memset(hcrx, 0, sizeof(*hcrx));
-
if (dp->dccps_packet_size >= TFRC_MIN_PACKET_SIZE &&
dp->dccps_packet_size <= TFRC_MAX_PACKET_SIZE)
hcrx->ccid3hcrx_s = dp->dccps_packet_size;
@@ -1067,7 +1049,6 @@ static int ccid3_hc_rx_init(struct sock
static void ccid3_hc_rx_exit(struct sock *sk)
{
struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);
- struct dccp_sock *dp = dccp_sk(sk);
BUG_ON(hcrx == NULL);
@@ -1078,9 +1059,6 @@ static void ccid3_hc_rx_exit(struct sock
/* Empty loss interval history */
dccp_li_hist_purge(ccid3_li_hist, &hcrx->ccid3hcrx_li_hist);
-
- kfree(dp->dccps_hc_rx_ccid_private);
- dp->dccps_hc_rx_ccid_private = NULL;
}
static void ccid3_hc_rx_get_info(struct sock *sk, struct tcp_info *info)
@@ -1166,10 +1144,11 @@ static int ccid3_hc_tx_getsockopt(struct
return 0;
}
-static struct ccid ccid3 = {
+static struct ccid_operations ccid3 = {
.ccid_id = 3,
.ccid_name = "ccid3",
.ccid_owner = THIS_MODULE,
+ .ccid_hc_tx_obj_size = sizeof(struct ccid3_hc_tx_sock),
.ccid_hc_tx_init = ccid3_hc_tx_init,
.ccid_hc_tx_exit = ccid3_hc_tx_exit,
.ccid_hc_tx_send_packet = ccid3_hc_tx_send_packet,
@@ -1177,6 +1156,7 @@ static struct ccid ccid3 = {
.ccid_hc_tx_packet_recv = ccid3_hc_tx_packet_recv,
.ccid_hc_tx_insert_options = ccid3_hc_tx_insert_options,
.ccid_hc_tx_parse_options = ccid3_hc_tx_parse_options,
+ .ccid_hc_rx_obj_size = sizeof(struct ccid3_hc_rx_sock),
.ccid_hc_rx_init = ccid3_hc_rx_init,
.ccid_hc_rx_exit = ccid3_hc_rx_exit,
.ccid_hc_rx_insert_options = ccid3_hc_rx_insert_options,
diff --git a/net/dccp/ccids/ccid3.h b/net/dccp/ccids/ccid3.h
index 0bde458..f18b96d 100644
--- a/net/dccp/ccids/ccid3.h
+++ b/net/dccp/ccids/ccid3.h
@@ -41,6 +41,7 @@
#include <linux/time.h>
#include <linux/types.h>
#include <linux/tfrc.h>
+#include "../ccid.h"
#define TFRC_MIN_PACKET_SIZE 16
#define TFRC_STD_PACKET_SIZE 256
@@ -135,12 +136,12 @@ struct ccid3_hc_rx_sock {
static inline struct ccid3_hc_tx_sock *ccid3_hc_tx_sk(const struct sock *sk)
{
- return dccp_sk(sk)->dccps_hc_tx_ccid_private;
+ return ccid_priv(dccp_sk(sk)->dccps_hc_tx_ccid);
}
static inline struct ccid3_hc_rx_sock *ccid3_hc_rx_sk(const struct sock *sk)
{
- return dccp_sk(sk)->dccps_hc_rx_ccid_private;
+ return ccid_priv(dccp_sk(sk)->dccps_hc_rx_ccid);
}
#endif /* _DCCP_CCID3_H_ */
diff --git a/net/dccp/input.c b/net/dccp/input.c
index 4b6d43d..67691a0 100644
--- a/net/dccp/input.c
+++ b/net/dccp/input.c
@@ -324,14 +324,6 @@ static int dccp_rcv_request_sent_state_p
dccp_set_seqno(&dp->dccps_swl,
max48(dp->dccps_swl, dp->dccps_isr));
- if (ccid_hc_rx_init(dp->dccps_hc_rx_ccid, sk) != 0 ||
- ccid_hc_tx_init(dp->dccps_hc_tx_ccid, sk) != 0) {
- ccid_hc_rx_exit(dp->dccps_hc_rx_ccid, sk);
- ccid_hc_tx_exit(dp->dccps_hc_tx_ccid, sk);
- /* FIXME: send appropriate RESET code */
- goto out_invalid_packet;
- }
-
dccp_sync_mss(sk, icsk->icsk_pmtu_cookie);
/*
diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c
index 14adcf9..266b6b2 100644
--- a/net/dccp/ipv4.c
+++ b/net/dccp/ipv4.c
@@ -1058,14 +1058,16 @@ int dccp_v4_init_sock(struct sock *sk)
if (dp->dccps_hc_rx_ackvec == NULL)
return -ENOMEM;
}
- dp->dccps_hc_rx_ccid = ccid_init(dp->dccps_options.dccpo_rx_ccid,
- sk);
- dp->dccps_hc_tx_ccid = ccid_init(dp->dccps_options.dccpo_tx_ccid,
- sk);
- if (dp->dccps_hc_rx_ccid == NULL ||
- dp->dccps_hc_tx_ccid == NULL) {
- ccid_exit(dp->dccps_hc_rx_ccid, sk);
- ccid_exit(dp->dccps_hc_tx_ccid, sk);
+ dp->dccps_hc_rx_ccid =
+ ccid_hc_rx_new(dp->dccps_options.dccpo_rx_ccid,
+ sk, GFP_KERNEL);
+ dp->dccps_hc_tx_ccid =
+ ccid_hc_tx_new(dp->dccps_options.dccpo_tx_ccid,
+ sk, GFP_KERNEL);
+ if (unlikely(dp->dccps_hc_rx_ccid == NULL ||
+ dp->dccps_hc_tx_ccid == NULL)) {
+ ccid_hc_rx_delete(dp->dccps_hc_rx_ccid, sk);
+ ccid_hc_tx_delete(dp->dccps_hc_tx_ccid, sk);
if (dp->dccps_options.dccpo_send_ack_vector) {
dccp_ackvec_free(dp->dccps_hc_rx_ackvec);
dp->dccps_hc_rx_ackvec = NULL;
@@ -1120,14 +1122,12 @@ int dccp_v4_destroy_sock(struct sock *sk
kfree(dp->dccps_service_list);
dp->dccps_service_list = NULL;
- ccid_hc_rx_exit(dp->dccps_hc_rx_ccid, sk);
- ccid_hc_tx_exit(dp->dccps_hc_tx_ccid, sk);
if (dp->dccps_options.dccpo_send_ack_vector) {
dccp_ackvec_free(dp->dccps_hc_rx_ackvec);
dp->dccps_hc_rx_ackvec = NULL;
}
- ccid_exit(dp->dccps_hc_rx_ccid, sk);
- ccid_exit(dp->dccps_hc_tx_ccid, sk);
+ ccid_hc_rx_delete(dp->dccps_hc_rx_ccid, sk);
+ ccid_hc_tx_delete(dp->dccps_hc_tx_ccid, sk);
dp->dccps_hc_rx_ccid = dp->dccps_hc_tx_ccid = NULL;
/* clean up feature negotiation state */
diff --git a/net/dccp/minisocks.c b/net/dccp/minisocks.c
index 9e1de59..5324fca 100644
--- a/net/dccp/minisocks.c
+++ b/net/dccp/minisocks.c
@@ -121,23 +121,21 @@ struct sock *dccp_create_openreq_child(s
if (newdp->dccps_options.dccpo_send_ack_vector) {
newdp->dccps_hc_rx_ackvec =
dccp_ackvec_alloc(GFP_ATOMIC);
- /*
- * XXX: We're using the same CCIDs set on the parent,
- * i.e. sk_clone copied the master sock and left the
- * CCID pointers for this child, that is why we do the
- * __ccid_get calls.
- */
if (unlikely(newdp->dccps_hc_rx_ackvec == NULL))
goto out_free;
}
- if (unlikely(ccid_hc_rx_init(newdp->dccps_hc_rx_ccid,
- newsk) != 0 ||
- ccid_hc_tx_init(newdp->dccps_hc_tx_ccid,
- newsk) != 0)) {
+ newdp->dccps_hc_rx_ccid =
+ ccid_hc_rx_new(newdp->dccps_options.dccpo_rx_ccid,
+ newsk, GFP_ATOMIC);
+ newdp->dccps_hc_tx_ccid =
+ ccid_hc_tx_new(newdp->dccps_options.dccpo_tx_ccid,
+ newsk, GFP_ATOMIC);
+ if (unlikely(newdp->dccps_hc_rx_ccid == NULL ||
+ newdp->dccps_hc_tx_ccid == NULL)) {
dccp_ackvec_free(newdp->dccps_hc_rx_ackvec);
- ccid_hc_rx_exit(newdp->dccps_hc_rx_ccid, newsk);
- ccid_hc_tx_exit(newdp->dccps_hc_tx_ccid, newsk);
+ ccid_hc_rx_delete(newdp->dccps_hc_rx_ccid, newsk);
+ ccid_hc_tx_delete(newdp->dccps_hc_tx_ccid, newsk);
out_free:
/* It is still raw copy of parent, so invalidate
* destructor and make plain sk_free() */
@@ -146,9 +144,6 @@ out_free:
return NULL;
}
- __ccid_get(newdp->dccps_hc_rx_ccid);
- __ccid_get(newdp->dccps_hc_tx_ccid);
-
/*
* Step 3: Process LISTEN state
*
^ permalink raw reply related
* Re: [PATCH 2/2][DCCP] CCID2: Drop sock reference count on timer
From: David S. Miller @ 2006-02-19 8:19 UTC (permalink / raw)
To: dccp
In-Reply-To: <39e6f6c70602150430x35cabcf1p9ea5b9538087e6ad@mail.gmail.com>
From: Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
Date: Wed, 15 Feb 2006 10:30:30 -0200
> Please consider pulling from:
>
> master.kernel.org:/pub/scm/linux/kernel/git/acme/net-2.6.17.git
>
> Now there are two outstanding csets in this tree.
Pulled, thanks Arnaldo.
^ permalink raw reply
* Re: panic in ccid3_hc_rx_packet_recv
From: Ian McDonald @ 2006-02-17 2:18 UTC (permalink / raw)
To: dccp
In-Reply-To: <39e6f6c70602160833j3973cf98xb21dde79da42ac78@mail.gmail.com>
On 2/17/06, Ian McDonald <imcdnzl@gmail.com> wrote:
> On 2/17/06, Arnaldo Carvalho de Melo <acme@ghostprotocols.net> wrote:
> > Long session over a wi-fi link, tons of packets already transmitted
> > then this panic, Ian,
> > can you take a look? There are two divisions in ccid3_hc_rx_packet_recv...
> >
> OK. Just had a quick look at it. Must be the second one as first is
> divided by an integer so no chance of divide by zero. Will look at it
> more later.
>
Just sent a patch for this...
--
Ian McDonald
http://wand.net.nz/~iam4
WAND Network Research Group
Department of Computer Science
University of Waikato
New Zealand
^ permalink raw reply
* [PATCH] DCCP: Divide by zero fix
From: Ian McDonald @ 2006-02-17 2:17 UTC (permalink / raw)
To: dccp
In rare circumstances 0 is returned by dccp_li_hist_calc_i_mean which
leads to a divide by zero in ccid3_hc_rx_packet_recv. Explicitly check
for zero return now. Update copyright notice at same time.
Found by Arnaldo
Signed-off-by: Ian McDonald <imcdnzl@gmail.com>
----
diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c
index 165fc40..fb4db88 100644
--- a/net/dccp/ccids/ccid3.c
+++ b/net/dccp/ccids/ccid3.c
@@ -2,7 +2,7 @@
* 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>
+ * Copyright (c) 2005-6 Ian McDonald <imcdnzl@gmail.com>
*
* An implementation of the DCCP protocol
*
@@ -925,7 +925,7 @@ static void ccid3_hc_rx_packet_recv(stru
struct dccp_rx_hist_entry *packet;
struct timeval now;
u8 win_count;
- u32 p_prev, r_sample, t_elapsed;
+ u32 p_prev, r_sample, t_elapsed, i_mean;
int ins;
BUG_ON(hcrx = NULL ||
@@ -1025,9 +1025,11 @@ static void ccid3_hc_rx_packet_recv(stru
p_prev = hcrx->ccid3hcrx_p;
/* Calculate loss event rate */
- if (!list_empty(&hcrx->ccid3hcrx_li_hist))
+ if (!list_empty(&hcrx->ccid3hcrx_li_hist)) {
+ i_mean = dccp_li_hist_calc_i_mean(&hcrx->ccid3hcrx_li_hist);
+ if (i_mean)
/* Scaling up by 1000000 as fixed decimal */
- hcrx->ccid3hcrx_p = 1000000 /
dccp_li_hist_calc_i_mean(&hcrx->ccid3hcrx_li_hist);
+ hcrx->ccid3hcrx_p = 1000000 / i_mean;
if (hcrx->ccid3hcrx_p > p_prev) {
ccid3_hc_rx_send_feedback(sk);
^ permalink raw reply related
* Re: panic in ccid3_hc_rx_packet_recv
From: Ian McDonald @ 2006-02-17 1:19 UTC (permalink / raw)
To: dccp
In-Reply-To: <39e6f6c70602160833j3973cf98xb21dde79da42ac78@mail.gmail.com>
On 2/17/06, Arnaldo Carvalho de Melo <acme@ghostprotocols.net> wrote:
> Long session over a wi-fi link, tons of packets already transmitted
> then this panic, Ian,
> can you take a look? There are two divisions in ccid3_hc_rx_packet_recv...
>
OK. Just had a quick look at it. Must be the second one as first is
divided by an integer so no chance of divide by zero. Will look at it
more later.
Ian
--
Ian McDonald
http://wand.net.nz/~iam4
WAND Network Research Group
Department of Computer Science
University of Waikato
New Zealand
^ permalink raw reply
* [BUG} DCCP - CCID2 Re: [RFC] CCID infrastructure improvements
From: Ian McDonald @ 2006-02-16 23:49 UTC (permalink / raw)
To: dccp
> As a baseline I downloaded acme-net-2.6.17.git and did some testing.
> When I test with netem in the middle between two boxes the transmitter
> locks solid....
>
> Test
> ./ttcp_acme -c -l500 -n100 -t jandi2
> ./ttcp_acme -c -l500 -r
>
> Netem configured as follows in middle box:
> sudo tc qdisc add dev lan1 root netem delay 50ms loss 10%
> sudo tc qdisc add dev lan0 root netem delay 50ms loss 10%
>
> I don't believe this happens with older version of DCCP (just pre
> CCID2) so I will start trying to track down....
>
> I don't have so much time so may take a little while. Feel free to
> investigate earlier if you wish.
>
OK. Run some more tests. This occurs only in CCID2 in
acme/net-2.6.17.git. CCID3 is fine without CCID2 compiled in from
.config. My transmit buffering is not OK either but that has not been
merged. Only occurs when I use netem in the middle. Locks the machine
solid on the transmitter but the receiver is OK.
Over to you Andrea unless I get further time to look at but not likely
for a few days at least...
Ian
--
Ian McDonald
http://wand.net.nz/~iam4
WAND Network Research Group
Department of Computer Science
University of Waikato
New Zealand
^ permalink raw reply
* Re: [PATCH 1/1] [DCCP]: Support multi-byte feature values and change ACK ratios
From: Arnaldo Carvalho de Melo @ 2006-02-16 20:40 UTC (permalink / raw)
To: dccp
Will review/merge this one today, thanks!
- Arnaldo
PS.: always CC dccp@vger.kernel.org on patch submissions, please :)
On 2/16/06, Andrea Bittau <a.bittau@cs.ucl.ac.uk> 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 <a.bittau@cs.ucl.ac.uk>
>
> ---
>
> 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)
>
^ permalink raw reply
* panic in ccid3_hc_rx_packet_recv
From: Arnaldo Carvalho de Melo @ 2006-02-16 16:33 UTC (permalink / raw)
To: dccp
Long session over a wi-fi link, tons of packets already transmitted
then this panic, Ian,
can you take a look? There are two divisions in ccid3_hc_rx_packet_recv...
- Arnaldo
[42956219.450000] DEBUG_PAGEALLOC
[42956219.450000] Modules linked in: dccp_diag inet_diag dccp_ccid3
dccp_tfrc_lib dccp ipv6 unix
[42956219.450000] CPU: 0
[42956219.450000] EIP: 0060:[<c485604b>] Not tainted VLI
[42956219.450000] EFLAGS: 00000246 (2.6.16-rc2acme #1)
[42956219.450000] EIP is at ccid3_hc_rx_packet_recv+0x33b/0x8f0 [dccp_ccid3]
[42956219.450000] eax: 000f4240 ebx: 00000000 ecx: 00000000 edx: 00000000
[42956219.450000] esi: c2a67574 edi: c2a675a4 ebp: c02eae60 esp: c02eadec
[42956219.450000] ds: 007b es: 007b ss: 0068
[42956219.450000] Process swapper (pid: 0, threadinfo¿2ea000 task¿28d200)
[42956219.450000] Stack: <0>c2a675a4 c02eae40 0b5b0b08 00000018
00000009 00000000 00000000 000016a3
[42956219.450000] 00000000 c2864f94 c2a67574 09864f94 c21033c4
c2a6759c c2a67574 00000006
[42956219.450000] 00000009 00000001 00015920 0002bf39 00000000
00001853 0004b7ce 00000018
[42956219.450000] Call Trace:
[42956219.450000] [<c01030cd>] show_stack_log_lvl+0xcd/0x120
[42956219.450000] [<c01032ae>] show_registers+0x18e/0x220
[42956219.450000] [<c01035a9>] die+0x109/0x230
[42956219.450000] [<c010389f>] do_trap+0x7f/0xb0
[42956219.450000] [<c010396e>] do_divide_error+0x9e/0xb0
[42956219.450000] [<c0102a67>] error_code+0x4f/0x54
[42956219.450000] [<c48420fb>] dccp_rcv_established+0x7b/0x200 [dccp]
[42956219.450000] [<c484336c>] dccp_v4_do_rcv+0x10c/0x2d0 [dccp]
[42956219.450000] [<c484432e>] dccp_v4_rcv+0x5fe/0x6a0 [dccp]
[42956219.450000] [<c021c4db>] ip_local_deliver+0xcb/0x230
[42956219.450000] [<c021c276>] ip_rcv+0x2a6/0x440
[42956219.450000] [<c0207fa6>] netif_receive_skb+0x166/0x1e0
[42956219.450000] [<c020809c>] process_backlog+0x7c/0x100
[42956219.450000] [<c0205452>] net_rx_action+0x72/0x110
[42956219.450000] [<c0114d62>] __do_softirq+0x52/0xb0
[42956219.450000] [<c0104721>] do_softirq+0x51/0x60
-
To unsubscribe from this list: send the line "unsubscribe dccp" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [RFC] CCID infrastructure improvements
From: Ian McDonald @ 2006-02-16 2:56 UTC (permalink / raw)
To: dccp
In-Reply-To: <39e6f6c70602151022v2d63a9d3nf88c0db59bfa36e9@mail.gmail.com>
>
> I tested with the code that is in the "ccid_operations" of my
> net-2.6.17 git tree (can
> you give it a try? Perhaps I did some last minute fix over the one you tested),
> but without a middle box, tomorrow I'll revive this parisc and use
> another machine
> to test on real machines, not just qemu.
>
Just doing more testing and the bug goes quite a while back - not sure
when last good version was. If time permits I'll test further using
git-bisect. It is fine when run on two machines talking directly
without loss/latency - only breaks on netem....
--
Ian McDonald
http://wand.net.nz/~iam4
WAND Network Research Group
Department of Computer Science
University of Waikato
New Zealand
^ permalink raw reply
* Re: [RFC] CCID infrastructure improvements
From: Arnaldo Carvalho de Melo @ 2006-02-16 2:50 UTC (permalink / raw)
To: dccp
In-Reply-To: <39e6f6c70602151022v2d63a9d3nf88c0db59bfa36e9@mail.gmail.com>
On 2/15/06, Ian McDonald <imcdnzl@gmail.com> wrote:
> On 2/16/06, Arnaldo Carvalho de Melo <acme@ghostprotocols.net> wrote:
> > Hi Ian, Andrea,
> >
> > Can somebody please poke holes in the attached patch? It moves
> > more code out of the
> > CCIDs into the CCID infrastructure, simplifying some stuff.
> >
> > With this rework ccid_operations becomes the struct proto
> > counterpart in ccid land (struct sock has a "operations" pointer to
> > struct proto).
> >
> > I saw the need for this when working on Andrea's ccid feature
> > negotiation patch, that I'm
> > now reworking to take advantage of the attached patch.
> >
> As a baseline I downloaded acme-net-2.6.17.git and did some testing.
> When I test with netem in the middle between two boxes the transmitter
> locks solid....
>
> Test
> ./ttcp_acme -c -l500 -n100 -t jandi2
> ./ttcp_acme -c -l500 -r
>
> Netem configured as follows in middle box:
> sudo tc qdisc add dev lan1 root netem delay 50ms loss 10%
> sudo tc qdisc add dev lan0 root netem delay 50ms loss 10%
>
> I don't believe this happens with older version of DCCP (just pre
> CCID2) so I will start trying to track down....
>
> I don't have so much time so may take a little while. Feel free to
> investigate earlier if you wish.
>
> As such I haven't tested the patch as baseline not stable...
>
http://master.kernel.org/git/?p=linux/kernel/git/acme/net-2.6.17.git;a=shortlog;hÌid_operations
I tested with the code that is in the "ccid_operations" of my
net-2.6.17 git tree (can
you give it a try? Perhaps I did some last minute fix over the one you tested),
but without a middle box, tomorrow I'll revive this parisc and use
another machine
to test on real machines, not just qemu.
- Arnaldo
^ permalink raw reply
* Re: [RFC] CCID infrastructure improvements
From: Ian McDonald @ 2006-02-16 1:18 UTC (permalink / raw)
To: dccp
In-Reply-To: <39e6f6c70602151022v2d63a9d3nf88c0db59bfa36e9@mail.gmail.com>
On 2/16/06, Arnaldo Carvalho de Melo <acme@ghostprotocols.net> wrote:
> Hi Ian, Andrea,
>
> Can somebody please poke holes in the attached patch? It moves
> more code out of the
> CCIDs into the CCID infrastructure, simplifying some stuff.
>
> With this rework ccid_operations becomes the struct proto
> counterpart in ccid land (struct sock has a "operations" pointer to
> struct proto).
>
> I saw the need for this when working on Andrea's ccid feature
> negotiation patch, that I'm
> now reworking to take advantage of the attached patch.
>
As a baseline I downloaded acme-net-2.6.17.git and did some testing.
When I test with netem in the middle between two boxes the transmitter
locks solid....
Test
./ttcp_acme -c -l500 -n100 -t jandi2
./ttcp_acme -c -l500 -r
Netem configured as follows in middle box:
sudo tc qdisc add dev lan1 root netem delay 50ms loss 10%
sudo tc qdisc add dev lan0 root netem delay 50ms loss 10%
I don't believe this happens with older version of DCCP (just pre
CCID2) so I will start trying to track down....
I don't have so much time so may take a little while. Feel free to
investigate earlier if you wish.
As such I haven't tested the patch as baseline not stable...
Ian
--
Ian McDonald
http://wand.net.nz/~iam4
WAND Network Research Group
Department of Computer Science
University of Waikato
New Zealand
^ permalink raw reply
* [RFC] CCID infrastructure improvements
From: Arnaldo Carvalho de Melo @ 2006-02-15 18:22 UTC (permalink / raw)
To: dccp
[-- Attachment #1: Type: text/plain, Size: 496 bytes --]
Hi Ian, Andrea,
Can somebody please poke holes in the attached patch? It moves
more code out of the
CCIDs into the CCID infrastructure, simplifying some stuff.
With this rework ccid_operations becomes the struct proto
counterpart in ccid land (struct sock has a "operations" pointer to
struct proto).
I saw the need for this when working on Andrea's ccid feature
negotiation patch, that I'm
now reworking to take advantage of the attached patch.
- Arnaldo
[-- Attachment #2: ccid_operations.patch --]
[-- Type: text/x-patch, Size: 24776 bytes --]
diff --git a/include/linux/dccp.h b/include/linux/dccp.h
index a70d1a2..bdd756c 100644
--- a/include/linux/dccp.h
+++ b/include/linux/dccp.h
@@ -478,8 +478,6 @@ struct dccp_sock {
__u32 dccps_mss_cache;
struct dccp_options dccps_options;
struct dccp_ackvec *dccps_hc_rx_ackvec;
- void *dccps_hc_rx_ccid_private;
- void *dccps_hc_tx_ccid_private;
struct ccid *dccps_hc_rx_ccid;
struct ccid *dccps_hc_tx_ccid;
struct dccp_options_received dccps_options_received;
diff --git a/net/dccp/ccid.c b/net/dccp/ccid.c
index 06b191a..49dea2a 100644
--- a/net/dccp/ccid.c
+++ b/net/dccp/ccid.c
@@ -13,7 +13,7 @@
#include "ccid.h"
-static struct ccid *ccids[CCID_MAX];
+static struct ccid_operations *ccids[CCID_MAX];
#if defined(CONFIG_SMP) || defined(CONFIG_PREEMPT)
static atomic_t ccids_lockct = ATOMIC_INIT(0);
static DEFINE_SPINLOCK(ccids_lock);
@@ -55,40 +55,103 @@ static inline void ccids_read_unlock(voi
#define ccids_read_unlock() do { } while(0)
#endif
-int ccid_register(struct ccid *ccid)
+static kmem_cache_t *ccid_kmem_cache_create(int obj_size, const char *fmt,...)
{
- int err;
+ kmem_cache_t *slab;
+ char slab_name_fmt[32], *slab_name;
+ va_list args;
+
+ va_start(args, fmt);
+ vsnprintf(slab_name_fmt, sizeof(slab_name_fmt), fmt, args);
+ va_end(args);
+
+ slab_name = kstrdup(slab_name_fmt, GFP_KERNEL);
+ if (slab_name == NULL)
+ return NULL;
+ slab = kmem_cache_create(slab_name, sizeof(struct ccid) + obj_size, 0,
+ SLAB_HWCACHE_ALIGN, NULL, NULL);
+ if (slab == NULL)
+ kfree(slab_name);
+ return slab;
+}
+
+static void ccid_kmem_cache_destroy(kmem_cache_t *slab)
+{
+ if (slab != NULL) {
+ const char *name = kmem_cache_name(slab);
+
+ kmem_cache_destroy(slab);
+ kfree(name);
+ }
+}
+
+int ccid_register(struct ccid_operations *ccid_ops)
+{
+ int err = -ENOBUFS;
+
+ ccid_ops->ccid_hc_rx_slab =
+ ccid_kmem_cache_create(ccid_ops->ccid_hc_rx_obj_size,
+ "%s_hc_rx_sock",
+ ccid_ops->ccid_name);
+ if (ccid_ops->ccid_hc_rx_slab == NULL)
+ goto out;
+
+ ccid_ops->ccid_hc_tx_slab =
+ ccid_kmem_cache_create(ccid_ops->ccid_hc_tx_obj_size,
+ "%s_hc_tx_sock",
+ ccid_ops->ccid_name);
+ if (ccid_ops->ccid_hc_tx_slab == NULL)
+ goto out_free_rx_slab;
ccids_write_lock();
err = -EEXIST;
- if (ccids[ccid->ccid_id] == NULL) {
- ccids[ccid->ccid_id] = ccid;
+ if (ccids[ccid_ops->ccid_id] == NULL) {
+ ccids[ccid_ops->ccid_id] = ccid_ops;
err = 0;
}
ccids_write_unlock();
- if (err == 0)
- pr_info("CCID: Registered CCID %d (%s)\n",
- ccid->ccid_id, ccid->ccid_name);
+ if (err != 0)
+ goto out_free_tx_slab;
+
+ pr_info("CCID: Registered CCID %d (%s)\n",
+ ccid_ops->ccid_id, ccid_ops->ccid_name);
+out:
return err;
+out_free_tx_slab:
+ ccid_kmem_cache_destroy(ccid_ops->ccid_hc_tx_slab);
+ ccid_ops->ccid_hc_tx_slab = NULL;
+ goto out;
+out_free_rx_slab:
+ ccid_kmem_cache_destroy(ccid_ops->ccid_hc_rx_slab);
+ ccid_ops->ccid_hc_rx_slab = NULL;
+ goto out;
}
EXPORT_SYMBOL_GPL(ccid_register);
-int ccid_unregister(struct ccid *ccid)
+int ccid_unregister(struct ccid_operations *ccid_ops)
{
ccids_write_lock();
- ccids[ccid->ccid_id] = NULL;
+ ccids[ccid_ops->ccid_id] = NULL;
ccids_write_unlock();
+
+ ccid_kmem_cache_destroy(ccid_ops->ccid_hc_tx_slab);
+ ccid_ops->ccid_hc_tx_slab = NULL;
+ ccid_kmem_cache_destroy(ccid_ops->ccid_hc_rx_slab);
+ ccid_ops->ccid_hc_rx_slab = NULL;
+
pr_info("CCID: Unregistered CCID %d (%s)\n",
- ccid->ccid_id, ccid->ccid_name);
+ ccid_ops->ccid_id, ccid_ops->ccid_name);
return 0;
}
EXPORT_SYMBOL_GPL(ccid_unregister);
-struct ccid *ccid_init(unsigned char id, struct sock *sk)
+static struct ccid *ccid_new(unsigned char id, struct sock *sk,
+ int rx, gfp_t gfp)
{
- struct ccid *ccid;
+ struct ccid_operations *ccid_ops;
+ struct ccid *ccid = NULL;
#ifdef CONFIG_KMOD
if (ccids[id] == NULL)
@@ -96,41 +159,92 @@ struct ccid *ccid_init(unsigned char id,
#endif
ccids_read_lock();
- ccid = ccids[id];
- if (ccid == NULL)
- goto out;
+ ccid_ops = ccids[id];
+ if (ccid_ops == NULL)
+ goto out_unlock;
+
+ if (!try_module_get(ccid_ops->ccid_owner))
+ goto out_unlock;
- if (!try_module_get(ccid->ccid_owner))
- goto out_err;
+ ccids_read_unlock();
- if (ccid->ccid_init != NULL && ccid->ccid_init(sk) != 0)
+ ccid = kmem_cache_alloc(rx ? ccid_ops->ccid_hc_rx_slab :
+ ccid_ops->ccid_hc_tx_slab, gfp);
+ if (ccid == NULL)
goto out_module_put;
+ ccid->ccid_ops = ccid_ops;
+ if (rx) {
+ memset(ccid + 1, 0, ccid_ops->ccid_hc_rx_obj_size);
+ if (ccid->ccid_ops->ccid_hc_rx_init != NULL &&
+ ccid->ccid_ops->ccid_hc_rx_init(ccid, sk) != 0)
+ goto out_free_ccid;
+ } else {
+ memset(ccid + 1, 0, ccid_ops->ccid_hc_tx_obj_size);
+ if (ccid->ccid_ops->ccid_hc_tx_init != NULL &&
+ ccid->ccid_ops->ccid_hc_tx_init(ccid, sk) != 0)
+ goto out_free_ccid;
+ }
out:
- ccids_read_unlock();
return ccid;
-out_module_put:
- module_put(ccid->ccid_owner);
-out_err:
+out_unlock:
+ ccids_read_unlock();
+ goto out;
+out_free_ccid:
+ kmem_cache_free(rx ? ccid_ops->ccid_hc_rx_slab :
+ ccid_ops->ccid_hc_tx_slab, ccid);
ccid = NULL;
+out_module_put:
+ module_put(ccid_ops->ccid_owner);
goto out;
}
-EXPORT_SYMBOL_GPL(ccid_init);
+struct ccid *ccid_hc_rx_new(unsigned char id, struct sock *sk, gfp_t gfp)
+{
+ return ccid_new(id, sk, 1, gfp);
+}
+
+EXPORT_SYMBOL_GPL(ccid_hc_rx_new);
+
+struct ccid *ccid_hc_tx_new(unsigned char id,struct sock *sk, gfp_t gfp)
+{
+ return ccid_new(id, sk, 0, gfp);
+}
+
+EXPORT_SYMBOL_GPL(ccid_hc_tx_new);
-void ccid_exit(struct ccid *ccid, struct sock *sk)
+static void ccid_delete(struct ccid *ccid, struct sock *sk, int rx)
{
+ struct ccid_operations *ccid_ops;
+
if (ccid == NULL)
return;
+ ccid_ops = ccid->ccid_ops;
+ if (rx) {
+ if (ccid_ops->ccid_hc_rx_exit != NULL)
+ ccid_ops->ccid_hc_rx_exit(sk);
+ kmem_cache_free(ccid_ops->ccid_hc_rx_slab, ccid);
+ } else {
+ if (ccid_ops->ccid_hc_tx_exit != NULL)
+ ccid_ops->ccid_hc_tx_exit(sk);
+ kmem_cache_free(ccid_ops->ccid_hc_tx_slab, ccid);
+ }
ccids_read_lock();
+ if (ccids[ccid_ops->ccid_id] != NULL)
+ module_put(ccid_ops->ccid_owner);
+ ccids_read_unlock();
+}
- if (ccids[ccid->ccid_id] != NULL) {
- if (ccid->ccid_exit != NULL)
- ccid->ccid_exit(sk);
- module_put(ccid->ccid_owner);
- }
+void ccid_hc_rx_delete(struct ccid *ccid, struct sock *sk)
+{
+ return ccid_delete(ccid, sk, 1);
+}
- ccids_read_unlock();
+EXPORT_SYMBOL_GPL(ccid_hc_rx_delete);
+
+void ccid_hc_tx_delete(struct ccid *ccid, struct sock *sk)
+{
+ return ccid_delete(ccid, sk, 0);
}
-EXPORT_SYMBOL_GPL(ccid_exit);
+EXPORT_SYMBOL_GPL(ccid_hc_tx_delete);
diff --git a/net/dccp/ccid.h b/net/dccp/ccid.h
index de681c6..cfc67df 100644
--- a/net/dccp/ccid.h
+++ b/net/dccp/ccid.h
@@ -23,14 +23,16 @@
struct tcp_info;
-struct ccid {
+struct ccid_operations {
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);
+ kmem_cache_t *ccid_hc_rx_slab;
+ __u32 ccid_hc_rx_obj_size;
+ kmem_cache_t *ccid_hc_tx_slab;
+ __u32 ccid_hc_tx_obj_size;
+ int (*ccid_hc_rx_init)(struct ccid *ccid, struct sock *sk);
+ int (*ccid_hc_tx_init)(struct ccid *ccid, 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,
@@ -67,75 +69,60 @@ struct ccid {
int __user *optlen);
};
-extern int ccid_register(struct ccid *ccid);
-extern int ccid_unregister(struct ccid *ccid);
+extern int ccid_register(struct ccid_operations *ccid_ops);
+extern int ccid_unregister(struct ccid_operations *ccid_ops);
-extern struct ccid *ccid_init(unsigned char id, struct sock *sk);
-extern void ccid_exit(struct ccid *ccid, struct sock *sk);
+struct ccid {
+ struct ccid_operations *ccid_ops;
+ char ccid_priv[0];
+};
-static inline void __ccid_get(struct ccid *ccid)
+static inline void *ccid_priv(const struct ccid *ccid)
{
- __module_get(ccid->ccid_owner);
+ return (void *)ccid->ccid_priv;
}
-static inline int ccid_hc_tx_send_packet(struct ccid *ccid, struct sock *sk,
- struct sk_buff *skb, int len)
-{
- int rc = 0;
- if (ccid->ccid_hc_tx_send_packet != NULL)
- rc = ccid->ccid_hc_tx_send_packet(sk, skb, len);
- return rc;
-}
+extern struct ccid *ccid_hc_rx_new(unsigned char id, struct sock *sk,
+ gfp_t gfp);
+extern struct ccid *ccid_hc_tx_new(unsigned char id, struct sock *sk,
+ gfp_t gfp);
-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);
-}
+extern void ccid_hc_rx_delete(struct ccid *ccid, struct sock *sk);
+extern void ccid_hc_tx_delete(struct ccid *ccid, struct sock *sk);
-static inline int ccid_hc_rx_init(struct ccid *ccid, struct sock *sk)
+static inline void __ccid_get(struct ccid *ccid)
{
- int rc = 0;
- if (ccid->ccid_hc_rx_init != NULL)
- rc = ccid->ccid_hc_rx_init(sk);
- return rc;
+ __module_get(ccid->ccid_ops->ccid_owner);
}
-static inline int ccid_hc_tx_init(struct ccid *ccid, struct sock *sk)
+static inline int ccid_hc_tx_send_packet(struct ccid *ccid, struct sock *sk,
+ struct sk_buff *skb, int len)
{
int rc = 0;
- if (ccid->ccid_hc_tx_init != NULL)
- rc = ccid->ccid_hc_tx_init(sk);
+ if (ccid->ccid_ops->ccid_hc_tx_send_packet != NULL)
+ rc = ccid->ccid_ops->ccid_hc_tx_send_packet(sk, skb, len);
return rc;
}
-static inline void ccid_hc_rx_exit(struct ccid *ccid, struct sock *sk)
-{
- if (ccid != NULL && ccid->ccid_hc_rx_exit != NULL &&
- dccp_sk(sk)->dccps_hc_rx_ccid_private != NULL)
- ccid->ccid_hc_rx_exit(sk);
-}
-
-static inline void ccid_hc_tx_exit(struct ccid *ccid, struct sock *sk)
+static inline void ccid_hc_tx_packet_sent(struct ccid *ccid, struct sock *sk,
+ int more, int len)
{
- if (ccid != NULL && ccid->ccid_hc_tx_exit != NULL &&
- dccp_sk(sk)->dccps_hc_tx_ccid_private != NULL)
- ccid->ccid_hc_tx_exit(sk);
+ if (ccid->ccid_ops->ccid_hc_tx_packet_sent != NULL)
+ ccid->ccid_ops->ccid_hc_tx_packet_sent(sk, more, len);
}
-
+
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);
+ if (ccid->ccid_ops->ccid_hc_rx_packet_recv != NULL)
+ ccid->ccid_ops->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);
+ if (ccid->ccid_ops->ccid_hc_tx_packet_recv != NULL)
+ ccid->ccid_ops->ccid_hc_tx_packet_recv(sk, skb);
}
static inline int ccid_hc_tx_parse_options(struct ccid *ccid, struct sock *sk,
@@ -144,8 +131,8 @@ static inline int ccid_hc_tx_parse_optio
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,
+ if (ccid->ccid_ops->ccid_hc_tx_parse_options != NULL)
+ rc = ccid->ccid_ops->ccid_hc_tx_parse_options(sk, option, len, idx,
value);
return rc;
}
@@ -156,37 +143,37 @@ static inline int ccid_hc_rx_parse_optio
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);
+ if (ccid->ccid_ops->ccid_hc_rx_parse_options != NULL)
+ rc = ccid->ccid_ops->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);
+ if (ccid->ccid_ops->ccid_hc_tx_insert_options != NULL)
+ ccid->ccid_ops->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);
+ if (ccid->ccid_ops->ccid_hc_rx_insert_options != NULL)
+ ccid->ccid_ops->ccid_hc_rx_insert_options(sk, skb);
}
static inline void ccid_hc_rx_get_info(struct ccid *ccid, struct sock *sk,
struct tcp_info *info)
{
- if (ccid->ccid_hc_rx_get_info != NULL)
- ccid->ccid_hc_rx_get_info(sk, info);
+ if (ccid->ccid_ops->ccid_hc_rx_get_info != NULL)
+ ccid->ccid_ops->ccid_hc_rx_get_info(sk, info);
}
static inline void ccid_hc_tx_get_info(struct ccid *ccid, struct sock *sk,
struct tcp_info *info)
{
- if (ccid->ccid_hc_tx_get_info != NULL)
- ccid->ccid_hc_tx_get_info(sk, info);
+ if (ccid->ccid_ops->ccid_hc_tx_get_info != NULL)
+ ccid->ccid_ops->ccid_hc_tx_get_info(sk, info);
}
static inline int ccid_hc_rx_getsockopt(struct ccid *ccid, struct sock *sk,
@@ -194,8 +181,8 @@ static inline int ccid_hc_rx_getsockopt(
u32 __user *optval, int __user *optlen)
{
int rc = -ENOPROTOOPT;
- if (ccid->ccid_hc_rx_getsockopt != NULL)
- rc = ccid->ccid_hc_rx_getsockopt(sk, optname, len,
+ if (ccid->ccid_ops->ccid_hc_rx_getsockopt != NULL)
+ rc = ccid->ccid_ops->ccid_hc_rx_getsockopt(sk, optname, len,
optval, optlen);
return rc;
}
@@ -205,8 +192,8 @@ static inline int ccid_hc_tx_getsockopt(
u32 __user *optval, int __user *optlen)
{
int rc = -ENOPROTOOPT;
- if (ccid->ccid_hc_tx_getsockopt != NULL)
- rc = ccid->ccid_hc_tx_getsockopt(sk, optname, len,
+ if (ccid->ccid_ops->ccid_hc_tx_getsockopt != NULL)
+ rc = ccid->ccid_ops->ccid_hc_tx_getsockopt(sk, optname, len,
optval, optlen);
return rc;
}
diff --git a/net/dccp/ccids/ccid2.c b/net/dccp/ccids/ccid2.c
index 6d4cb43..8f964dc 100644
--- a/net/dccp/ccids/ccid2.c
+++ b/net/dccp/ccids/ccid2.c
@@ -54,12 +54,12 @@ static const int ccid2_seq_len = 128;
static inline struct ccid2_hc_tx_sock *ccid2_hc_tx_sk(const struct sock *sk)
{
- return dccp_sk(sk)->dccps_hc_tx_ccid_private;
+ return ccid_priv(dccp_sk(sk)->dccps_hc_tx_ccid);
}
static inline struct ccid2_hc_rx_sock *ccid2_hc_rx_sk(const struct sock *sk)
{
- return dccp_sk(sk)->dccps_hc_rx_ccid_private;
+ return ccid_priv(dccp_sk(sk)->dccps_hc_rx_ccid);
}
#ifdef CCID2_DEBUG
@@ -707,19 +707,12 @@ static void ccid2_hc_tx_packet_recv(stru
ccid2_hc_tx_check_sanity(hctx);
}
-static int ccid2_hc_tx_init(struct sock *sk)
+static int ccid2_hc_tx_init(struct ccid *ccid, struct sock *sk)
{
- struct dccp_sock *dp = dccp_sk(sk);
- struct ccid2_hc_tx_sock *hctx;
+ struct ccid2_hc_tx_sock *hctx = ccid_priv(ccid);
int seqcount = ccid2_seq_len;
int i;
- dp->dccps_hc_tx_ccid_private = kzalloc(sizeof(*hctx), gfp_any());
- if (dp->dccps_hc_tx_ccid_private == NULL)
- return -ENOMEM;
-
- hctx = ccid2_hc_tx_sk(sk);
-
/* XXX init variables with proper values */
hctx->ccid2hctx_cwnd = 1;
hctx->ccid2hctx_ssthresh = 10;
@@ -728,11 +721,9 @@ static int ccid2_hc_tx_init(struct sock
/* XXX init ~ to window size... */
hctx->ccid2hctx_seqbuf = kmalloc(sizeof(*hctx->ccid2hctx_seqbuf) *
seqcount, gfp_any());
- if (hctx->ccid2hctx_seqbuf == NULL) {
- kfree(dp->dccps_hc_tx_ccid_private);
- dp->dccps_hc_tx_ccid_private = NULL;
+ if (hctx->ccid2hctx_seqbuf == NULL)
return -ENOMEM;
- }
+
for (i = 0; i < (seqcount - 1); i++) {
hctx->ccid2hctx_seqbuf[i].ccid2s_next =
&hctx->ccid2hctx_seqbuf[i + 1];
@@ -763,15 +754,11 @@ static int ccid2_hc_tx_init(struct sock
static void ccid2_hc_tx_exit(struct sock *sk)
{
- struct dccp_sock *dp = dccp_sk(sk);
struct ccid2_hc_tx_sock *hctx = ccid2_hc_tx_sk(sk);
ccid2_hc_tx_kill_rto_timer(sk);
-
kfree(hctx->ccid2hctx_seqbuf);
-
- kfree(dp->dccps_hc_tx_ccid_private);
- dp->dccps_hc_tx_ccid_private = NULL;
+ hctx->ccid2hctx_seqbuf = NULL;
}
static void ccid2_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb)
@@ -791,33 +778,17 @@ static void ccid2_hc_rx_packet_recv(stru
}
}
-static int ccid2_hc_rx_init(struct sock *sk)
-{
- struct dccp_sock *dp = dccp_sk(sk);
- dp->dccps_hc_rx_ccid_private = kzalloc(sizeof(struct ccid2_hc_rx_sock),
- gfp_any());
- return dp->dccps_hc_rx_ccid_private == NULL ? -ENOMEM : 0;
-}
-
-static void ccid2_hc_rx_exit(struct sock *sk)
-{
- struct dccp_sock *dp = dccp_sk(sk);
-
- kfree(dp->dccps_hc_rx_ccid_private);
- dp->dccps_hc_rx_ccid_private = NULL;
-}
-
-static struct ccid ccid2 = {
+static struct ccid_operations ccid2 = {
.ccid_id = 2,
.ccid_name = "ccid2",
.ccid_owner = THIS_MODULE,
+ .ccid_hc_tx_obj_size = sizeof(struct ccid2_hc_tx_sock),
.ccid_hc_tx_init = ccid2_hc_tx_init,
.ccid_hc_tx_exit = ccid2_hc_tx_exit,
.ccid_hc_tx_send_packet = ccid2_hc_tx_send_packet,
.ccid_hc_tx_packet_sent = ccid2_hc_tx_packet_sent,
.ccid_hc_tx_packet_recv = ccid2_hc_tx_packet_recv,
- .ccid_hc_rx_init = ccid2_hc_rx_init,
- .ccid_hc_rx_exit = ccid2_hc_rx_exit,
+ .ccid_hc_rx_obj_size = sizeof(struct ccid2_hc_rx_sock),
.ccid_hc_rx_packet_recv = ccid2_hc_rx_packet_recv,
};
diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c
index 165fc40..a357c15 100644
--- a/net/dccp/ccids/ccid3.c
+++ b/net/dccp/ccids/ccid3.c
@@ -647,17 +647,10 @@ static int ccid3_hc_tx_parse_options(str
return rc;
}
-static int ccid3_hc_tx_init(struct sock *sk)
+static int ccid3_hc_tx_init(struct ccid *ccid, struct sock *sk)
{
struct dccp_sock *dp = dccp_sk(sk);
- struct ccid3_hc_tx_sock *hctx;
-
- dp->dccps_hc_tx_ccid_private = kmalloc(sizeof(*hctx), gfp_any());
- if (dp->dccps_hc_tx_ccid_private == NULL)
- return -ENOMEM;
-
- hctx = ccid3_hc_tx_sk(sk);
- memset(hctx, 0, sizeof(*hctx));
+ struct ccid3_hc_tx_sock *hctx = ccid_priv(ccid);
if (dp->dccps_packet_size >= TFRC_MIN_PACKET_SIZE &&
dp->dccps_packet_size <= TFRC_MAX_PACKET_SIZE)
@@ -680,7 +673,6 @@ static int ccid3_hc_tx_init(struct sock
static void ccid3_hc_tx_exit(struct sock *sk)
{
- struct dccp_sock *dp = dccp_sk(sk);
struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);
BUG_ON(hctx == NULL);
@@ -690,9 +682,6 @@ static void ccid3_hc_tx_exit(struct sock
/* Empty packet history */
dccp_tx_hist_purge(ccid3_tx_hist, &hctx->ccid3hctx_hist);
-
- kfree(dp->dccps_hc_tx_ccid_private);
- dp->dccps_hc_tx_ccid_private = NULL;
}
/*
@@ -1035,20 +1024,13 @@ static void ccid3_hc_rx_packet_recv(stru
}
}
-static int ccid3_hc_rx_init(struct sock *sk)
+static int ccid3_hc_rx_init(struct ccid *ccid, struct sock *sk)
{
struct dccp_sock *dp = dccp_sk(sk);
- struct ccid3_hc_rx_sock *hcrx;
+ struct ccid3_hc_rx_sock *hcrx = ccid_priv(ccid);
ccid3_pr_debug("%s, sk=%p\n", dccp_role(sk), sk);
- dp->dccps_hc_rx_ccid_private = kmalloc(sizeof(*hcrx), gfp_any());
- if (dp->dccps_hc_rx_ccid_private == NULL)
- return -ENOMEM;
-
- hcrx = ccid3_hc_rx_sk(sk);
- memset(hcrx, 0, sizeof(*hcrx));
-
if (dp->dccps_packet_size >= TFRC_MIN_PACKET_SIZE &&
dp->dccps_packet_size <= TFRC_MAX_PACKET_SIZE)
hcrx->ccid3hcrx_s = dp->dccps_packet_size;
@@ -1067,7 +1049,6 @@ static int ccid3_hc_rx_init(struct sock
static void ccid3_hc_rx_exit(struct sock *sk)
{
struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);
- struct dccp_sock *dp = dccp_sk(sk);
BUG_ON(hcrx == NULL);
@@ -1078,9 +1059,6 @@ static void ccid3_hc_rx_exit(struct sock
/* Empty loss interval history */
dccp_li_hist_purge(ccid3_li_hist, &hcrx->ccid3hcrx_li_hist);
-
- kfree(dp->dccps_hc_rx_ccid_private);
- dp->dccps_hc_rx_ccid_private = NULL;
}
static void ccid3_hc_rx_get_info(struct sock *sk, struct tcp_info *info)
@@ -1166,10 +1144,11 @@ static int ccid3_hc_tx_getsockopt(struct
return 0;
}
-static struct ccid ccid3 = {
+static struct ccid_operations ccid3 = {
.ccid_id = 3,
.ccid_name = "ccid3",
.ccid_owner = THIS_MODULE,
+ .ccid_hc_tx_obj_size = sizeof(struct ccid3_hc_tx_sock),
.ccid_hc_tx_init = ccid3_hc_tx_init,
.ccid_hc_tx_exit = ccid3_hc_tx_exit,
.ccid_hc_tx_send_packet = ccid3_hc_tx_send_packet,
@@ -1177,6 +1156,7 @@ static struct ccid ccid3 = {
.ccid_hc_tx_packet_recv = ccid3_hc_tx_packet_recv,
.ccid_hc_tx_insert_options = ccid3_hc_tx_insert_options,
.ccid_hc_tx_parse_options = ccid3_hc_tx_parse_options,
+ .ccid_hc_rx_obj_size = sizeof(struct ccid3_hc_rx_sock),
.ccid_hc_rx_init = ccid3_hc_rx_init,
.ccid_hc_rx_exit = ccid3_hc_rx_exit,
.ccid_hc_rx_insert_options = ccid3_hc_rx_insert_options,
diff --git a/net/dccp/ccids/ccid3.h b/net/dccp/ccids/ccid3.h
index 0bde458..f1db3d6 100644
--- a/net/dccp/ccids/ccid3.h
+++ b/net/dccp/ccids/ccid3.h
@@ -135,12 +135,12 @@ struct ccid3_hc_rx_sock {
static inline struct ccid3_hc_tx_sock *ccid3_hc_tx_sk(const struct sock *sk)
{
- return dccp_sk(sk)->dccps_hc_tx_ccid_private;
+ return ccid_priv(dccp_sk(sk)->dccps_hc_tx_ccid);
}
static inline struct ccid3_hc_rx_sock *ccid3_hc_rx_sk(const struct sock *sk)
{
- return dccp_sk(sk)->dccps_hc_rx_ccid_private;
+ return ccid_priv(dccp_sk(sk)->dccps_hc_rx_ccid);
}
#endif /* _DCCP_CCID3_H_ */
diff --git a/net/dccp/input.c b/net/dccp/input.c
index 4b6d43d..67691a0 100644
--- a/net/dccp/input.c
+++ b/net/dccp/input.c
@@ -324,14 +324,6 @@ static int dccp_rcv_request_sent_state_p
dccp_set_seqno(&dp->dccps_swl,
max48(dp->dccps_swl, dp->dccps_isr));
- if (ccid_hc_rx_init(dp->dccps_hc_rx_ccid, sk) != 0 ||
- ccid_hc_tx_init(dp->dccps_hc_tx_ccid, sk) != 0) {
- ccid_hc_rx_exit(dp->dccps_hc_rx_ccid, sk);
- ccid_hc_tx_exit(dp->dccps_hc_tx_ccid, sk);
- /* FIXME: send appropriate RESET code */
- goto out_invalid_packet;
- }
-
dccp_sync_mss(sk, icsk->icsk_pmtu_cookie);
/*
diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c
index 14adcf9..266b6b2 100644
--- a/net/dccp/ipv4.c
+++ b/net/dccp/ipv4.c
@@ -1058,14 +1058,16 @@ int dccp_v4_init_sock(struct sock *sk)
if (dp->dccps_hc_rx_ackvec == NULL)
return -ENOMEM;
}
- dp->dccps_hc_rx_ccid = ccid_init(dp->dccps_options.dccpo_rx_ccid,
- sk);
- dp->dccps_hc_tx_ccid = ccid_init(dp->dccps_options.dccpo_tx_ccid,
- sk);
- if (dp->dccps_hc_rx_ccid == NULL ||
- dp->dccps_hc_tx_ccid == NULL) {
- ccid_exit(dp->dccps_hc_rx_ccid, sk);
- ccid_exit(dp->dccps_hc_tx_ccid, sk);
+ dp->dccps_hc_rx_ccid =
+ ccid_hc_rx_new(dp->dccps_options.dccpo_rx_ccid,
+ sk, GFP_KERNEL);
+ dp->dccps_hc_tx_ccid =
+ ccid_hc_tx_new(dp->dccps_options.dccpo_tx_ccid,
+ sk, GFP_KERNEL);
+ if (unlikely(dp->dccps_hc_rx_ccid == NULL ||
+ dp->dccps_hc_tx_ccid == NULL)) {
+ ccid_hc_rx_delete(dp->dccps_hc_rx_ccid, sk);
+ ccid_hc_tx_delete(dp->dccps_hc_tx_ccid, sk);
if (dp->dccps_options.dccpo_send_ack_vector) {
dccp_ackvec_free(dp->dccps_hc_rx_ackvec);
dp->dccps_hc_rx_ackvec = NULL;
@@ -1120,14 +1122,12 @@ int dccp_v4_destroy_sock(struct sock *sk
kfree(dp->dccps_service_list);
dp->dccps_service_list = NULL;
- ccid_hc_rx_exit(dp->dccps_hc_rx_ccid, sk);
- ccid_hc_tx_exit(dp->dccps_hc_tx_ccid, sk);
if (dp->dccps_options.dccpo_send_ack_vector) {
dccp_ackvec_free(dp->dccps_hc_rx_ackvec);
dp->dccps_hc_rx_ackvec = NULL;
}
- ccid_exit(dp->dccps_hc_rx_ccid, sk);
- ccid_exit(dp->dccps_hc_tx_ccid, sk);
+ ccid_hc_rx_delete(dp->dccps_hc_rx_ccid, sk);
+ ccid_hc_tx_delete(dp->dccps_hc_tx_ccid, sk);
dp->dccps_hc_rx_ccid = dp->dccps_hc_tx_ccid = NULL;
/* clean up feature negotiation state */
diff --git a/net/dccp/minisocks.c b/net/dccp/minisocks.c
index 9e1de59..ded63d1 100644
--- a/net/dccp/minisocks.c
+++ b/net/dccp/minisocks.c
@@ -131,13 +131,17 @@ struct sock *dccp_create_openreq_child(s
goto out_free;
}
- if (unlikely(ccid_hc_rx_init(newdp->dccps_hc_rx_ccid,
- newsk) != 0 ||
- ccid_hc_tx_init(newdp->dccps_hc_tx_ccid,
- newsk) != 0)) {
+ newdp->dccps_hc_rx_ccid =
+ ccid_hc_rx_new(newdp->dccps_options.dccpo_rx_ccid,
+ newsk, GFP_ATOMIC);
+ newdp->dccps_hc_tx_ccid =
+ ccid_hc_tx_new(newdp->dccps_options.dccpo_tx_ccid,
+ newsk, GFP_ATOMIC);
+ if (unlikely(newdp->dccps_hc_rx_ccid == NULL ||
+ newdp->dccps_hc_tx_ccid == NULL)) {
dccp_ackvec_free(newdp->dccps_hc_rx_ackvec);
- ccid_hc_rx_exit(newdp->dccps_hc_rx_ccid, newsk);
- ccid_hc_tx_exit(newdp->dccps_hc_tx_ccid, newsk);
+ ccid_hc_rx_delete(newdp->dccps_hc_rx_ccid, newsk);
+ ccid_hc_tx_delete(newdp->dccps_hc_tx_ccid, newsk);
out_free:
/* It is still raw copy of parent, so invalidate
* destructor and make plain sk_free() */
^ permalink raw reply related
* Re: [PATCH] 1/1 dccp: transmit buffering
From: Ian McDonald @ 2006-02-15 17:48 UTC (permalink / raw)
To: dccp
In-Reply-To: <cbec11ac0602061504y3507004dnf8b13d089d9fceba@mail.gmail.com>
> > Still bit short of time but tested some more and found it clashed with
> > feature negotiation so will need more work :-( One of the problems is
> > with the code stopping the retransmit timer in feature negotiation.
> > Removing that fixes it for standard test cases but it then fails with
> > delay of 50 ms and 10% loss using netem where it worked without
> > feature negotiation for me. Might be bottom half locking perhaps -
> > haven't tested changes to that yet.
>
> Andrea, can you take a look at this one?
It may yet be a race I think. You can wait until I test my code with
bh locks (it only happens when my code is merged...)
>
> Well, it checks, look at its usage of mod_timer to see if the timer was
> pending and if not drop the lock, i.e. no refcount leakage here, if you
> are worried about races that is why we use the timer routine under
> bh_lock_sock()/bh_release_sock(), look at ccid3_hc_tx_no_feedback_timer.
That is my exact worry - races - so that solves it now for me. Thanks
a lot Arnaldo.
--
Ian McDonald
http://wand.net.nz/~iam4
WAND Network Research Group
Department of Computer Science
University of Waikato
New Zealand
^ permalink raw reply
* [PATCH 1/X] [DCCP]: Actually change the CCID upon negotiation.
From: Andrea Bittau @ 2006-02-15 12:49 UTC (permalink / raw)
To: dccp
Change the CCID upon successful feature negotiation.
Signed-off-by: Andrea Bittau <a.bittau@cs.ucl.ac.uk>
---
diff --git a/net/dccp/feat.c b/net/dccp/feat.c
index fb74260..094f1ba 100644
--- a/net/dccp/feat.c
+++ b/net/dccp/feat.c
@@ -14,6 +14,7 @@
#include <linux/module.h>
#include "dccp.h"
+#include "ccid.h"
#include "feat.h"
#define DCCP_FEAT_SP_NOAGREE (-123)
@@ -26,6 +27,8 @@ int dccp_feat_change(struct sock *sk, u8
dccp_pr_debug("feat change type=%d feat=%d\n", type, feature);
+ /* XXX sanity check feat change request */
+
/* check if that feature is already being negotiated */
list_for_each_entry(opt, &dp->dccps_options.dccpo_pending,
dccpop_node) {
@@ -62,11 +65,81 @@ int dccp_feat_change(struct sock *sk, u8
EXPORT_SYMBOL_GPL(dccp_feat_change);
+static int dccp_feat_update_ccid(struct sock *sk, u8 type, u8 val)
+{
+ struct dccp_sock *dp = dccp_sk(sk);
+ struct ccid **ccid;
+ u8 *oldval;
+ /* XXX function ptrs to inline functions. Is this legal? */
+ int (*ccid_hc_init)(struct ccid *ccid, struct sock *sk);
+ void (*ccid_hc_exit)(struct ccid *ccid, struct sock *sk);
+ int rc = 0;
+
+ /* figure out if we are changing our CCID or the peer's */
+ if (type = DCCPO_CHANGE_L) {
+ ccid = &dp->dccps_hc_tx_ccid;
+ oldval = &dp->dccps_options.dccpo_tx_ccid;
+ ccid_hc_init = &ccid_hc_tx_init;
+ ccid_hc_exit = &ccid_hc_tx_exit;
+ } else {
+ ccid = &dp->dccps_hc_rx_ccid;
+ oldval = &dp->dccps_options.dccpo_rx_ccid;
+ ccid_hc_init = &ccid_hc_rx_init;
+ ccid_hc_exit = &ccid_hc_rx_exit;
+ }
+
+ /* check if nothing is being changed. */
+ if (*oldval = val)
+ return 0;
+
+ /* kill old CCID */
+ /* ccid_hc_init() is called only upon receiving a RESPONSE packet */
+ if (sk->sk_state != DCCP_REQUESTING)
+ ccid_hc_exit(*ccid, sk);
+ ccid_exit(*ccid, sk);
+
+ /* switch CCID */
+ *ccid = ccid_init(val, sk);
+ if (*ccid = NULL) {
+ /* XXX OK we have a problem here. socket will remain without
+ * CCID. I think the only sensible thing is to kill the socket
+ * ASAP. Ideally, one would make sure the new CCID could be
+ * allocated before the old one is deleted. The problem is that
+ * ccid_init might play with the private ccid state of sk,
+ * that's why it's safer to first kill the old ccid.
+ */
+ rc = -ENOMEM;
+ goto out_exit;
+ }
+ if (sk->sk_state != DCCP_REQUESTING) {
+ rc = ccid_hc_init(*ccid, sk);
+ if (rc)
+ goto out_exit;
+ }
+
+ *oldval = val;
+
+out:
+ return rc;
+out_exit:
+ ccid_exit(*ccid, sk);
+ *ccid = NULL;
+ goto out;
+}
+
/* XXX taking only u8 vals */
static int dccp_feat_update(struct sock *sk, u8 type, u8 feat, u8 val)
{
- /* FIXME implement */
dccp_pr_debug("changing [%d] feat %d to %d\n", type, feat, val);
+
+ switch (feat) {
+ case DCCPF_CCID:
+ return dccp_feat_update_ccid(sk, type, val);
+
+ default:
+ WARN_ON(1); /* XXX implement */
+ break;
+ }
return 0;
}
^ permalink raw reply related
* Re: [PATCH 1/1]: [CCID2]: Fix the use of the RTO timer
From: Arnaldo Carvalho de Melo @ 2006-02-15 12:31 UTC (permalink / raw)
To: dccp
In-Reply-To: <20060215013015.GA14878@tribal.sorbonet.org>
On 2/14/06, Andrea Bittau <a.bittau@cs.ucl.ac.uk> wrote:
> Drop sock reference count on timer expiration and reset.
>
> There was a hybrid use of standard timers and sk_timers. This caused the
> reference count of the sock to be incorrect when resetting the RTO timer. The
> sock reference count should now be correct, enabling its destruction, and
> allowing the DCCP module to be unloaded.
Thanks, applied and pushed to Dave, I wonder why I didn't catched this...
- Arnaldo
^ permalink raw reply
* [PATCH 2/2][DCCP] CCID2: Drop sock reference count on timer expiration and reset
From: Arnaldo Carvalho de Melo @ 2006-02-15 12:30 UTC (permalink / raw)
To: dccp
[-- Attachment #1: Type: text/plain, Size: 198 bytes --]
Hi David,
Please consider pulling from:
master.kernel.org:/pub/scm/linux/kernel/git/acme/net-2.6.17.git
Now there are two outstanding csets in this tree.
Best Regards,
- Arnaldo
[-- Attachment #2: 2.patch --]
[-- Type: text/x-patch, Size: 3366 bytes --]
tree 9f3ff0a05e7a2ac51825e18c0af0233ad9c26541
parent 75548ffb3813e123bf90d20b595c01fd363b8160
author Andrea Bittau <a.bittau@cs.ucl.ac.uk> 1140006497 -0200
committer Arnaldo Carvalho de Melo <acme@mandriva.com> 1140006497 -0200
[DCCP] CCID2: Drop sock reference count on timer expiration and reset.
There was a hybrid use of standard timers and sk_timers. This caused the
reference count of the sock to be incorrect when resetting the RTO timer. The
sock reference count should now be correct, enabling its destruction, and
allowing the DCCP module to be unloaded.
Signed-off-by: Andrea Bittau <a.bittau@cs.ucl.ac.uk>
Signed-off-by: Arnaldo Carvalho de Melo <acme@mandriva.com>
------------------------------------------------------------------------------
ccid2.c | 26 +++++++++++++++-----------
1 file changed, 15 insertions(+), 11 deletions(-)
------------------------------------------------------------------------------
diff --git a/net/dccp/ccids/ccid2.c b/net/dccp/ccids/ccid2.c
index 5495980..6d4cb43 100644
--- a/net/dccp/ccids/ccid2.c
+++ b/net/dccp/ccids/ccid2.c
@@ -234,7 +234,7 @@ static void ccid2_hc_tx_rto_expire(unsig
ccid2_hc_tx_check_sanity(hctx);
out:
bh_unlock_sock(sk);
-/* sock_put(sk); */
+ sock_put(sk);
}
static void ccid2_start_rto_timer(struct sock *sk)
@@ -399,10 +399,12 @@ out_invalid_option:
return -1;
}
-static void ccid2_hc_tx_kill_rto_timer(struct ccid2_hc_tx_sock *hctx)
+static void ccid2_hc_tx_kill_rto_timer(struct sock *sk)
{
- if (del_timer(&hctx->ccid2hctx_rtotimer))
- ccid2_pr_debug("deleted RTO timer\n");
+ struct ccid2_hc_tx_sock *hctx = ccid2_hc_tx_sk(sk);
+
+ sk_stop_timer(sk, &hctx->ccid2hctx_rtotimer);
+ ccid2_pr_debug("deleted RTO timer\n");
}
static inline void ccid2_new_ack(struct sock *sk,
@@ -496,17 +498,19 @@ static inline void ccid2_new_ack(struct
}
/* we got a new ack, so re-start RTO timer */
- ccid2_hc_tx_kill_rto_timer(hctx);
+ ccid2_hc_tx_kill_rto_timer(sk);
ccid2_start_rto_timer(sk);
}
-static void ccid2_hc_tx_dec_pipe(struct ccid2_hc_tx_sock *hctx)
+static void ccid2_hc_tx_dec_pipe(struct sock *sk)
{
+ struct ccid2_hc_tx_sock *hctx = ccid2_hc_tx_sk(sk);
+
hctx->ccid2hctx_pipe--;
BUG_ON(hctx->ccid2hctx_pipe < 0);
if (hctx->ccid2hctx_pipe == 0)
- ccid2_hc_tx_kill_rto_timer(hctx);
+ ccid2_hc_tx_kill_rto_timer(sk);
}
static void ccid2_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
@@ -627,7 +631,7 @@ static void ccid2_hc_tx_packet_recv(stru
seqp->ccid2s_acked = 1;
ccid2_pr_debug("Got ack for %llu\n",
seqp->ccid2s_seq);
- ccid2_hc_tx_dec_pipe(hctx);
+ ccid2_hc_tx_dec_pipe(sk);
}
if (seqp == hctx->ccid2hctx_seqt) {
done = 1;
@@ -674,7 +678,7 @@ static void ccid2_hc_tx_packet_recv(stru
while (1) {
if (!seqp->ccid2s_acked) {
loss = 1;
- ccid2_hc_tx_dec_pipe(hctx);
+ ccid2_hc_tx_dec_pipe(sk);
}
if (seqp == hctx->ccid2hctx_seqt)
break;
@@ -760,9 +764,9 @@ static int ccid2_hc_tx_init(struct sock
static void ccid2_hc_tx_exit(struct sock *sk)
{
struct dccp_sock *dp = dccp_sk(sk);
- struct ccid2_hc_tx_sock *hctx = dp->dccps_hc_tx_ccid_private;
+ struct ccid2_hc_tx_sock *hctx = ccid2_hc_tx_sk(sk);
- ccid2_hc_tx_kill_rto_timer(hctx);
+ ccid2_hc_tx_kill_rto_timer(sk);
kfree(hctx->ccid2hctx_seqbuf);
^ permalink raw reply related
* Re: [PATCH] 1/1 dccp: transmit buffering
From: Arnaldo Carvalho de Melo @ 2006-02-15 11:57 UTC (permalink / raw)
To: dccp
In-Reply-To: <cbec11ac0602061504y3507004dnf8b13d089d9fceba@mail.gmail.com>
Ian McDonald wrote:
> On 2/7/06, Ian McDonald <imcdnzl@gmail.com> wrote:
>>> See the comments below, I guess we don't need yet another lock :-)
>> Will look at some more about locks as time permits - we take
>> possession of our house today :-)
>
> Still bit short of time but tested some more and found it clashed with
> feature negotiation so will need more work :-( One of the problems is
> with the code stopping the retransmit timer in feature negotiation.
> Removing that fixes it for standard test cases but it then fails with
> delay of 50 ms and 10% loss using netem where it worked without
> feature negotiation for me. Might be bottom half locking perhaps -
> haven't tested changes to that yet.
Andrea, can you take a look at this one?
>> The reason for this is to allow sending of queued packets when user
>> application says close...
>>
>>> sk_reset_timer() please, so that we make sure we have a reference count
>>> for the sock as its going to be on a timer
>> As I read the timer source code if the timer returns do I have to do a
>> sock_put (I am guessing so as I don't see how it would happen
>> elsewise).
>
> Are you able to answer this?
Yes, you have to do a sock_put at the end of the timer routine, if
you restart the timer with sk_reset_timer it'll grab another refcount,
so the one done at first firing the timer will be dropped by the
sock_put at the end of the timer routine.
>>> sk_stop_timer please, to drop the refcount we grabbed with sk_reset_timer()
>>> elsewhere.
>>>
>> The thing with sk_stop_timer is that it doesn't check if the timer
>> routine is in use which would mean that we can have problems (I hit
>> this in testing). I presume the best way is to create a
>> sk_stop_timer_sync rather than use generic timer...
>
> Any comments on this anyone as this is how I intend to code it...
Well, it checks, look at its usage of mod_timer to see if the timer was
pending and if not drop the lock, i.e. no refcount leakage here, if you
are worried about races that is why we use the timer routine under
bh_lock_sock()/bh_release_sock(), look at ccid3_hc_tx_no_feedback_timer.
Or is it some other worry you have? can you elaborate? If you need
mod_timer return forwarded to the sk_reset_user() user we can do it if
needed.
- Arnaldo
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox