[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>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Arnaldo Carvalho de Melo 2006-03-20 19:21:44 -08:00 committed by David S. Miller
parent f38c39d6ce
commit 91f0ebf7b6
10 changed files with 265 additions and 217 deletions

View file

@ -478,8 +478,6 @@ struct dccp_sock {
__u32 dccps_mss_cache; __u32 dccps_mss_cache;
struct dccp_options dccps_options; struct dccp_options dccps_options;
struct dccp_ackvec *dccps_hc_rx_ackvec; 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_rx_ccid;
struct ccid *dccps_hc_tx_ccid; struct ccid *dccps_hc_tx_ccid;
struct dccp_options_received dccps_options_received; struct dccp_options_received dccps_options_received;

View file

@ -13,7 +13,7 @@
#include "ccid.h" #include "ccid.h"
static struct ccid *ccids[CCID_MAX]; static struct ccid_operations *ccids[CCID_MAX];
#if defined(CONFIG_SMP) || defined(CONFIG_PREEMPT) #if defined(CONFIG_SMP) || defined(CONFIG_PREEMPT)
static atomic_t ccids_lockct = ATOMIC_INIT(0); static atomic_t ccids_lockct = ATOMIC_INIT(0);
static DEFINE_SPINLOCK(ccids_lock); static DEFINE_SPINLOCK(ccids_lock);
@ -55,82 +55,202 @@ static inline void ccids_read_unlock(void)
#define ccids_read_unlock() do { } while(0) #define ccids_read_unlock() do { } while(0)
#endif #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(); ccids_write_lock();
err = -EEXIST; err = -EEXIST;
if (ccids[ccid->ccid_id] == NULL) { if (ccids[ccid_ops->ccid_id] == NULL) {
ccids[ccid->ccid_id] = ccid; ccids[ccid_ops->ccid_id] = ccid_ops;
err = 0; err = 0;
} }
ccids_write_unlock(); ccids_write_unlock();
if (err == 0) if (err != 0)
pr_info("CCID: Registered CCID %d (%s)\n", goto out_free_tx_slab;
ccid->ccid_id, ccid->ccid_name);
pr_info("CCID: Registered CCID %d (%s)\n",
ccid_ops->ccid_id, ccid_ops->ccid_name);
out:
return err; 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); EXPORT_SYMBOL_GPL(ccid_register);
int ccid_unregister(struct ccid *ccid) int ccid_unregister(struct ccid_operations *ccid_ops)
{ {
ccids_write_lock(); ccids_write_lock();
ccids[ccid->ccid_id] = NULL; ccids[ccid_ops->ccid_id] = NULL;
ccids_write_unlock(); 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", pr_info("CCID: Unregistered CCID %d (%s)\n",
ccid->ccid_id, ccid->ccid_name); ccid_ops->ccid_id, ccid_ops->ccid_name);
return 0; return 0;
} }
EXPORT_SYMBOL_GPL(ccid_unregister); 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;
#ifdef CONFIG_KMOD
if (ccids[id] == NULL)
request_module("net-dccp-ccid-%d", id);
#endif
ccids_read_lock(); ccids_read_lock();
#ifdef CONFIG_KMOD
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
ccid_ops = ccids[id];
if (ccid_ops == NULL)
goto out_unlock;
ccid = ccids[id]; if (!try_module_get(ccid_ops->ccid_owner))
if (ccid == NULL) goto out_unlock;
goto out;
if (!try_module_get(ccid->ccid_owner))
goto out_err;
if (ccid->ccid_init != NULL && ccid->ccid_init(sk) != 0)
goto out_module_put;
out:
ccids_read_unlock(); ccids_read_unlock();
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:
return ccid; return ccid;
out_module_put: out_unlock:
module_put(ccid->ccid_owner); ccids_read_unlock();
out_err: goto out;
out_free_ccid:
kmem_cache_free(rx ? ccid_ops->ccid_hc_rx_slab :
ccid_ops->ccid_hc_tx_slab, ccid);
ccid = NULL; ccid = NULL;
out_module_put:
module_put(ccid_ops->ccid_owner);
goto out; goto out;
} }
EXPORT_SYMBOL_GPL(ccid_init); EXPORT_SYMBOL_GPL(ccid_new);
void ccid_exit(struct ccid *ccid, struct sock *sk) 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);
static void ccid_delete(struct ccid *ccid, struct sock *sk, int rx)
{
struct ccid_operations *ccid_ops;
if (ccid == NULL) if (ccid == NULL)
return; return;
ccids_read_lock(); ccid_ops = ccid->ccid_ops;
if (rx) {
if (ccids[ccid->ccid_id] != NULL) { if (ccid_ops->ccid_hc_rx_exit != NULL)
if (ccid->ccid_exit != NULL) ccid_ops->ccid_hc_rx_exit(sk);
ccid->ccid_exit(sk); kmem_cache_free(ccid_ops->ccid_hc_rx_slab, ccid);
module_put(ccid->ccid_owner); } 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(); ccids_read_unlock();
} }
EXPORT_SYMBOL_GPL(ccid_exit); void ccid_hc_rx_delete(struct ccid *ccid, struct sock *sk)
{
ccid_delete(ccid, sk, 1);
}
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_hc_tx_delete);

View file

@ -23,14 +23,16 @@
struct tcp_info; struct tcp_info;
struct ccid { struct ccid_operations {
unsigned char ccid_id; unsigned char ccid_id;
const char *ccid_name; const char *ccid_name;
struct module *ccid_owner; struct module *ccid_owner;
int (*ccid_init)(struct sock *sk); kmem_cache_t *ccid_hc_rx_slab;
void (*ccid_exit)(struct sock *sk); __u32 ccid_hc_rx_obj_size;
int (*ccid_hc_rx_init)(struct sock *sk); kmem_cache_t *ccid_hc_tx_slab;
int (*ccid_hc_tx_init)(struct sock *sk); __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_rx_exit)(struct sock *sk);
void (*ccid_hc_tx_exit)(struct sock *sk); void (*ccid_hc_tx_exit)(struct sock *sk);
void (*ccid_hc_rx_packet_recv)(struct sock *sk, void (*ccid_hc_rx_packet_recv)(struct sock *sk,
@ -67,75 +69,58 @@ struct ccid {
int __user *optlen); int __user *optlen);
}; };
extern int ccid_register(struct ccid *ccid); extern int ccid_register(struct ccid_operations *ccid_ops);
extern int ccid_unregister(struct ccid *ccid); extern int ccid_unregister(struct ccid_operations *ccid_ops);
extern struct ccid *ccid_init(unsigned char id, struct sock *sk); struct ccid {
extern void ccid_exit(struct ccid *ccid, struct sock *sk); 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, static inline int ccid_hc_tx_send_packet(struct ccid *ccid, struct sock *sk,
struct sk_buff *skb, int len) struct sk_buff *skb, int len)
{ {
int rc = 0; int rc = 0;
if (ccid->ccid_hc_tx_send_packet != NULL) if (ccid->ccid_ops->ccid_hc_tx_send_packet != NULL)
rc = ccid->ccid_hc_tx_send_packet(sk, skb, len); rc = ccid->ccid_ops->ccid_hc_tx_send_packet(sk, skb, len);
return rc; return rc;
} }
static inline void ccid_hc_tx_packet_sent(struct ccid *ccid, struct sock *sk, static inline void ccid_hc_tx_packet_sent(struct ccid *ccid, struct sock *sk,
int more, int len) int more, int len)
{ {
if (ccid->ccid_hc_tx_packet_sent != NULL) if (ccid->ccid_ops->ccid_hc_tx_packet_sent != NULL)
ccid->ccid_hc_tx_packet_sent(sk, more, len); 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, static inline void ccid_hc_rx_packet_recv(struct ccid *ccid, struct sock *sk,
struct sk_buff *skb) struct sk_buff *skb)
{ {
if (ccid->ccid_hc_rx_packet_recv != NULL) if (ccid->ccid_ops->ccid_hc_rx_packet_recv != NULL)
ccid->ccid_hc_rx_packet_recv(sk, skb); ccid->ccid_ops->ccid_hc_rx_packet_recv(sk, skb);
} }
static inline void ccid_hc_tx_packet_recv(struct ccid *ccid, struct sock *sk, static inline void ccid_hc_tx_packet_recv(struct ccid *ccid, struct sock *sk,
struct sk_buff *skb) struct sk_buff *skb)
{ {
if (ccid->ccid_hc_tx_packet_recv != NULL) if (ccid->ccid_ops->ccid_hc_tx_packet_recv != NULL)
ccid->ccid_hc_tx_packet_recv(sk, skb); ccid->ccid_ops->ccid_hc_tx_packet_recv(sk, skb);
} }
static inline int ccid_hc_tx_parse_options(struct ccid *ccid, struct sock *sk, 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_options(struct ccid *ccid, struct sock *sk,
unsigned char* value) unsigned char* value)
{ {
int rc = 0; int rc = 0;
if (ccid->ccid_hc_tx_parse_options != NULL) if (ccid->ccid_ops->ccid_hc_tx_parse_options != NULL)
rc = ccid->ccid_hc_tx_parse_options(sk, option, len, idx, rc = ccid->ccid_ops->ccid_hc_tx_parse_options(sk, option, len, idx,
value); value);
return rc; return rc;
} }
@ -156,37 +141,37 @@ static inline int ccid_hc_rx_parse_options(struct ccid *ccid, struct sock *sk,
unsigned char* value) unsigned char* value)
{ {
int rc = 0; int rc = 0;
if (ccid->ccid_hc_rx_parse_options != NULL) if (ccid->ccid_ops->ccid_hc_rx_parse_options != NULL)
rc = ccid->ccid_hc_rx_parse_options(sk, option, len, idx, value); rc = ccid->ccid_ops->ccid_hc_rx_parse_options(sk, option, len, idx, value);
return rc; return rc;
} }
static inline void ccid_hc_tx_insert_options(struct ccid *ccid, struct sock *sk, static inline void ccid_hc_tx_insert_options(struct ccid *ccid, struct sock *sk,
struct sk_buff *skb) struct sk_buff *skb)
{ {
if (ccid->ccid_hc_tx_insert_options != NULL) if (ccid->ccid_ops->ccid_hc_tx_insert_options != NULL)
ccid->ccid_hc_tx_insert_options(sk, skb); ccid->ccid_ops->ccid_hc_tx_insert_options(sk, skb);
} }
static inline void ccid_hc_rx_insert_options(struct ccid *ccid, struct sock *sk, static inline void ccid_hc_rx_insert_options(struct ccid *ccid, struct sock *sk,
struct sk_buff *skb) struct sk_buff *skb)
{ {
if (ccid->ccid_hc_rx_insert_options != NULL) if (ccid->ccid_ops->ccid_hc_rx_insert_options != NULL)
ccid->ccid_hc_rx_insert_options(sk, skb); ccid->ccid_ops->ccid_hc_rx_insert_options(sk, skb);
} }
static inline void ccid_hc_rx_get_info(struct ccid *ccid, struct sock *sk, static inline void ccid_hc_rx_get_info(struct ccid *ccid, struct sock *sk,
struct tcp_info *info) struct tcp_info *info)
{ {
if (ccid->ccid_hc_rx_get_info != NULL) if (ccid->ccid_ops->ccid_hc_rx_get_info != NULL)
ccid->ccid_hc_rx_get_info(sk, info); ccid->ccid_ops->ccid_hc_rx_get_info(sk, info);
} }
static inline void ccid_hc_tx_get_info(struct ccid *ccid, struct sock *sk, static inline void ccid_hc_tx_get_info(struct ccid *ccid, struct sock *sk,
struct tcp_info *info) struct tcp_info *info)
{ {
if (ccid->ccid_hc_tx_get_info != NULL) if (ccid->ccid_ops->ccid_hc_tx_get_info != NULL)
ccid->ccid_hc_tx_get_info(sk, info); ccid->ccid_ops->ccid_hc_tx_get_info(sk, info);
} }
static inline int ccid_hc_rx_getsockopt(struct ccid *ccid, struct sock *sk, static inline int ccid_hc_rx_getsockopt(struct ccid *ccid, struct sock *sk,
@ -194,8 +179,8 @@ static inline int ccid_hc_rx_getsockopt(struct ccid *ccid, struct sock *sk,
u32 __user *optval, int __user *optlen) u32 __user *optval, int __user *optlen)
{ {
int rc = -ENOPROTOOPT; int rc = -ENOPROTOOPT;
if (ccid->ccid_hc_rx_getsockopt != NULL) if (ccid->ccid_ops->ccid_hc_rx_getsockopt != NULL)
rc = ccid->ccid_hc_rx_getsockopt(sk, optname, len, rc = ccid->ccid_ops->ccid_hc_rx_getsockopt(sk, optname, len,
optval, optlen); optval, optlen);
return rc; return rc;
} }
@ -205,8 +190,8 @@ static inline int ccid_hc_tx_getsockopt(struct ccid *ccid, struct sock *sk,
u32 __user *optval, int __user *optlen) u32 __user *optval, int __user *optlen)
{ {
int rc = -ENOPROTOOPT; int rc = -ENOPROTOOPT;
if (ccid->ccid_hc_tx_getsockopt != NULL) if (ccid->ccid_ops->ccid_hc_tx_getsockopt != NULL)
rc = ccid->ccid_hc_tx_getsockopt(sk, optname, len, rc = ccid->ccid_ops->ccid_hc_tx_getsockopt(sk, optname, len,
optval, optlen); optval, optlen);
return rc; return rc;
} }

View file

@ -52,16 +52,6 @@ static int ccid2_debug;
static const int ccid2_seq_len = 128; 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 #ifdef CCID2_DEBUG
static void ccid2_hc_tx_check_sanity(const struct ccid2_hc_tx_sock *hctx) 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(struct sock *sk, struct sk_buff *skb)
ccid2_hc_tx_check_sanity(hctx); 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 = ccid_priv(ccid);
struct ccid2_hc_tx_sock *hctx;
int seqcount = ccid2_seq_len; int seqcount = ccid2_seq_len;
int i; 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 */ /* XXX init variables with proper values */
hctx->ccid2hctx_cwnd = 1; hctx->ccid2hctx_cwnd = 1;
hctx->ccid2hctx_ssthresh = 10; hctx->ccid2hctx_ssthresh = 10;
@ -728,11 +711,9 @@ static int ccid2_hc_tx_init(struct sock *sk)
/* XXX init ~ to window size... */ /* XXX init ~ to window size... */
hctx->ccid2hctx_seqbuf = kmalloc(sizeof(*hctx->ccid2hctx_seqbuf) * hctx->ccid2hctx_seqbuf = kmalloc(sizeof(*hctx->ccid2hctx_seqbuf) *
seqcount, gfp_any()); seqcount, gfp_any());
if (hctx->ccid2hctx_seqbuf == NULL) { if (hctx->ccid2hctx_seqbuf == NULL)
kfree(dp->dccps_hc_tx_ccid_private);
dp->dccps_hc_tx_ccid_private = NULL;
return -ENOMEM; return -ENOMEM;
}
for (i = 0; i < (seqcount - 1); i++) { for (i = 0; i < (seqcount - 1); i++) {
hctx->ccid2hctx_seqbuf[i].ccid2s_next = hctx->ccid2hctx_seqbuf[i].ccid2s_next =
&hctx->ccid2hctx_seqbuf[i + 1]; &hctx->ccid2hctx_seqbuf[i + 1];
@ -763,15 +744,11 @@ static int ccid2_hc_tx_init(struct sock *sk)
static void ccid2_hc_tx_exit(struct sock *sk) 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); struct ccid2_hc_tx_sock *hctx = ccid2_hc_tx_sk(sk);
ccid2_hc_tx_kill_rto_timer(sk); ccid2_hc_tx_kill_rto_timer(sk);
kfree(hctx->ccid2hctx_seqbuf); kfree(hctx->ccid2hctx_seqbuf);
hctx->ccid2hctx_seqbuf = NULL;
kfree(dp->dccps_hc_tx_ccid_private);
dp->dccps_hc_tx_ccid_private = NULL;
} }
static void ccid2_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb) 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(struct sock *sk, struct sk_buff *skb)
} }
} }
static int ccid2_hc_rx_init(struct sock *sk) static struct ccid_operations ccid2 = {
{
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 = {
.ccid_id = 2, .ccid_id = 2,
.ccid_name = "ccid2", .ccid_name = "ccid2",
.ccid_owner = THIS_MODULE, .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_init = ccid2_hc_tx_init,
.ccid_hc_tx_exit = ccid2_hc_tx_exit, .ccid_hc_tx_exit = ccid2_hc_tx_exit,
.ccid_hc_tx_send_packet = ccid2_hc_tx_send_packet, .ccid_hc_tx_send_packet = ccid2_hc_tx_send_packet,
.ccid_hc_tx_packet_sent = ccid2_hc_tx_packet_sent, .ccid_hc_tx_packet_sent = ccid2_hc_tx_packet_sent,
.ccid_hc_tx_packet_recv = ccid2_hc_tx_packet_recv, .ccid_hc_tx_packet_recv = ccid2_hc_tx_packet_recv,
.ccid_hc_rx_init = ccid2_hc_rx_init, .ccid_hc_rx_obj_size = sizeof(struct ccid2_hc_rx_sock),
.ccid_hc_rx_exit = ccid2_hc_rx_exit,
.ccid_hc_rx_packet_recv = ccid2_hc_rx_packet_recv, .ccid_hc_rx_packet_recv = ccid2_hc_rx_packet_recv,
}; };

View file

@ -20,6 +20,13 @@
#ifndef _DCCP_CCID2_H_ #ifndef _DCCP_CCID2_H_
#define _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 { struct ccid2_seq {
u64 ccid2s_seq; u64 ccid2s_seq;
unsigned long ccid2s_sent; unsigned long ccid2s_sent;
@ -66,4 +73,13 @@ struct ccid2_hc_rx_sock {
int ccid2hcrx_data; 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_ */ #endif /* _DCCP_CCID2_H_ */

View file

@ -647,17 +647,10 @@ static int ccid3_hc_tx_parse_options(struct sock *sk, unsigned char option,
return rc; 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 dccp_sock *dp = dccp_sk(sk);
struct ccid3_hc_tx_sock *hctx; struct ccid3_hc_tx_sock *hctx = ccid_priv(ccid);
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));
if (dp->dccps_packet_size >= TFRC_MIN_PACKET_SIZE && if (dp->dccps_packet_size >= TFRC_MIN_PACKET_SIZE &&
dp->dccps_packet_size <= TFRC_MAX_PACKET_SIZE) dp->dccps_packet_size <= TFRC_MAX_PACKET_SIZE)
@ -680,7 +673,6 @@ static int ccid3_hc_tx_init(struct sock *sk)
static void ccid3_hc_tx_exit(struct sock *sk) 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); struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);
BUG_ON(hctx == NULL); BUG_ON(hctx == NULL);
@ -690,9 +682,6 @@ static void ccid3_hc_tx_exit(struct sock *sk)
/* Empty packet history */ /* Empty packet history */
dccp_tx_hist_purge(ccid3_tx_hist, &hctx->ccid3hctx_hist); dccp_tx_hist_purge(ccid3_tx_hist, &hctx->ccid3hctx_hist);
kfree(dp->dccps_hc_tx_ccid_private);
dp->dccps_hc_tx_ccid_private = NULL;
} }
/* /*
@ -1039,20 +1028,13 @@ static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb)
} }
} }
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 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); 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 && if (dp->dccps_packet_size >= TFRC_MIN_PACKET_SIZE &&
dp->dccps_packet_size <= TFRC_MAX_PACKET_SIZE) dp->dccps_packet_size <= TFRC_MAX_PACKET_SIZE)
hcrx->ccid3hcrx_s = dp->dccps_packet_size; hcrx->ccid3hcrx_s = dp->dccps_packet_size;
@ -1071,7 +1053,6 @@ static int ccid3_hc_rx_init(struct sock *sk)
static void ccid3_hc_rx_exit(struct sock *sk) static void ccid3_hc_rx_exit(struct sock *sk)
{ {
struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk); struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);
struct dccp_sock *dp = dccp_sk(sk);
BUG_ON(hcrx == NULL); BUG_ON(hcrx == NULL);
@ -1082,9 +1063,6 @@ static void ccid3_hc_rx_exit(struct sock *sk)
/* Empty loss interval history */ /* Empty loss interval history */
dccp_li_hist_purge(ccid3_li_hist, &hcrx->ccid3hcrx_li_hist); 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) static void ccid3_hc_rx_get_info(struct sock *sk, struct tcp_info *info)
@ -1170,10 +1148,11 @@ static int ccid3_hc_tx_getsockopt(struct sock *sk, const int optname, int len,
return 0; return 0;
} }
static struct ccid ccid3 = { static struct ccid_operations ccid3 = {
.ccid_id = 3, .ccid_id = 3,
.ccid_name = "ccid3", .ccid_name = "ccid3",
.ccid_owner = THIS_MODULE, .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_init = ccid3_hc_tx_init,
.ccid_hc_tx_exit = ccid3_hc_tx_exit, .ccid_hc_tx_exit = ccid3_hc_tx_exit,
.ccid_hc_tx_send_packet = ccid3_hc_tx_send_packet, .ccid_hc_tx_send_packet = ccid3_hc_tx_send_packet,
@ -1181,6 +1160,7 @@ static struct ccid ccid3 = {
.ccid_hc_tx_packet_recv = ccid3_hc_tx_packet_recv, .ccid_hc_tx_packet_recv = ccid3_hc_tx_packet_recv,
.ccid_hc_tx_insert_options = ccid3_hc_tx_insert_options, .ccid_hc_tx_insert_options = ccid3_hc_tx_insert_options,
.ccid_hc_tx_parse_options = ccid3_hc_tx_parse_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_init = ccid3_hc_rx_init,
.ccid_hc_rx_exit = ccid3_hc_rx_exit, .ccid_hc_rx_exit = ccid3_hc_rx_exit,
.ccid_hc_rx_insert_options = ccid3_hc_rx_insert_options, .ccid_hc_rx_insert_options = ccid3_hc_rx_insert_options,

View file

@ -41,6 +41,7 @@
#include <linux/time.h> #include <linux/time.h>
#include <linux/types.h> #include <linux/types.h>
#include <linux/tfrc.h> #include <linux/tfrc.h>
#include "../ccid.h"
#define TFRC_MIN_PACKET_SIZE 16 #define TFRC_MIN_PACKET_SIZE 16
#define TFRC_STD_PACKET_SIZE 256 #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) 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) 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_ */ #endif /* _DCCP_CCID3_H_ */

View file

@ -324,14 +324,6 @@ static int dccp_rcv_request_sent_state_process(struct sock *sk,
dccp_set_seqno(&dp->dccps_swl, dccp_set_seqno(&dp->dccps_swl,
max48(dp->dccps_swl, dp->dccps_isr)); 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); dccp_sync_mss(sk, icsk->icsk_pmtu_cookie);
/* /*

View file

@ -1058,14 +1058,16 @@ int dccp_v4_init_sock(struct sock *sk)
if (dp->dccps_hc_rx_ackvec == NULL) if (dp->dccps_hc_rx_ackvec == NULL)
return -ENOMEM; return -ENOMEM;
} }
dp->dccps_hc_rx_ccid = ccid_init(dp->dccps_options.dccpo_rx_ccid, dp->dccps_hc_rx_ccid =
sk); ccid_hc_rx_new(dp->dccps_options.dccpo_rx_ccid,
dp->dccps_hc_tx_ccid = ccid_init(dp->dccps_options.dccpo_tx_ccid, sk, GFP_KERNEL);
sk); dp->dccps_hc_tx_ccid =
if (dp->dccps_hc_rx_ccid == NULL || ccid_hc_tx_new(dp->dccps_options.dccpo_tx_ccid,
dp->dccps_hc_tx_ccid == NULL) { sk, GFP_KERNEL);
ccid_exit(dp->dccps_hc_rx_ccid, sk); if (unlikely(dp->dccps_hc_rx_ccid == NULL ||
ccid_exit(dp->dccps_hc_tx_ccid, sk); 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) { if (dp->dccps_options.dccpo_send_ack_vector) {
dccp_ackvec_free(dp->dccps_hc_rx_ackvec); dccp_ackvec_free(dp->dccps_hc_rx_ackvec);
dp->dccps_hc_rx_ackvec = NULL; dp->dccps_hc_rx_ackvec = NULL;
@ -1120,14 +1122,12 @@ int dccp_v4_destroy_sock(struct sock *sk)
kfree(dp->dccps_service_list); kfree(dp->dccps_service_list);
dp->dccps_service_list = NULL; 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) { if (dp->dccps_options.dccpo_send_ack_vector) {
dccp_ackvec_free(dp->dccps_hc_rx_ackvec); dccp_ackvec_free(dp->dccps_hc_rx_ackvec);
dp->dccps_hc_rx_ackvec = NULL; dp->dccps_hc_rx_ackvec = NULL;
} }
ccid_exit(dp->dccps_hc_rx_ccid, sk); ccid_hc_rx_delete(dp->dccps_hc_rx_ccid, sk);
ccid_exit(dp->dccps_hc_tx_ccid, sk); ccid_hc_tx_delete(dp->dccps_hc_tx_ccid, sk);
dp->dccps_hc_rx_ccid = dp->dccps_hc_tx_ccid = NULL; dp->dccps_hc_rx_ccid = dp->dccps_hc_tx_ccid = NULL;
/* clean up feature negotiation state */ /* clean up feature negotiation state */

View file

@ -121,23 +121,21 @@ struct sock *dccp_create_openreq_child(struct sock *sk,
if (newdp->dccps_options.dccpo_send_ack_vector) { if (newdp->dccps_options.dccpo_send_ack_vector) {
newdp->dccps_hc_rx_ackvec = newdp->dccps_hc_rx_ackvec =
dccp_ackvec_alloc(GFP_ATOMIC); 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)) if (unlikely(newdp->dccps_hc_rx_ackvec == NULL))
goto out_free; goto out_free;
} }
if (unlikely(ccid_hc_rx_init(newdp->dccps_hc_rx_ccid, newdp->dccps_hc_rx_ccid =
newsk) != 0 || ccid_hc_rx_new(newdp->dccps_options.dccpo_rx_ccid,
ccid_hc_tx_init(newdp->dccps_hc_tx_ccid, newsk, GFP_ATOMIC);
newsk) != 0)) { 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); dccp_ackvec_free(newdp->dccps_hc_rx_ackvec);
ccid_hc_rx_exit(newdp->dccps_hc_rx_ccid, newsk); ccid_hc_rx_delete(newdp->dccps_hc_rx_ccid, newsk);
ccid_hc_tx_exit(newdp->dccps_hc_tx_ccid, newsk); ccid_hc_tx_delete(newdp->dccps_hc_tx_ccid, newsk);
out_free: out_free:
/* It is still raw copy of parent, so invalidate /* It is still raw copy of parent, so invalidate
* destructor and make plain sk_free() */ * destructor and make plain sk_free() */
@ -146,9 +144,6 @@ struct sock *dccp_create_openreq_child(struct sock *sk,
return NULL; return NULL;
} }
__ccid_get(newdp->dccps_hc_rx_ccid);
__ccid_get(newdp->dccps_hc_tx_ccid);
/* /*
* Step 3: Process LISTEN state * Step 3: Process LISTEN state
* *