[DCCP]: Introduce the DCCP Kernel hacking menu
Only available if CONFIG_DEBUG_KERNEL is enabled in the "Kernel
Hacking" Menu.
Signed-off-by: Arnaldo Carvalho de Melo <acme@mandriva.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
diff --git a/net/dccp/Kconfig b/net/dccp/Kconfig
index 6760830..3023f70 100644
--- a/net/dccp/Kconfig
+++ b/net/dccp/Kconfig
@@ -26,4 +26,25 @@
source "net/dccp/ccids/Kconfig"
+menu "DCCP Kernel Hacking"
+ depends on IP_DCCP=m && DEBUG_KERNEL=y
+
+config IP_DCCP_DEBUG
+ bool "DCCP debug messages"
+ ---help---
+ Only use this if you're hacking DCCP.
+
+ Just say N.
+
+config IP_DCCP_UNLOAD_HACK
+ depends on IP_DCCP_CCID3=m
+ bool "DCCP control sock unload hack"
+ ---help---
+ Enable this to be able to unload the dccp module when the it
+ has only one refcount held, the control sock one. Just execute
+ "rmmod dccp_ccid3 dccp"
+
+ Just say N.
+endmenu
+
endmenu
diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c
index edf9740..09274f3 100644
--- a/net/dccp/ccids/ccid3.c
+++ b/net/dccp/ccids/ccid3.c
@@ -2078,6 +2078,15 @@
static __exit void ccid3_module_exit(void)
{
+#ifdef CONFIG_IP_DCCP_UNLOAD_HACK
+ /*
+ * Hack to use while developing, so that we get rid of the control
+ * sock, that is what keeps a refcount on dccp.ko -acme
+ */
+ extern void dccp_ctl_sock_exit(void);
+
+ dccp_ctl_sock_exit();
+#endif
ccid_unregister(&ccid3);
if (ccid3_tx_hist != NULL) {
diff --git a/net/dccp/dccp.h b/net/dccp/dccp.h
index 62e735f..270f194 100644
--- a/net/dccp/dccp.h
+++ b/net/dccp/dccp.h
@@ -11,14 +11,13 @@
* published by the Free Software Foundation.
*/
+#include <linux/config.h>
#include <linux/dccp.h>
#include <net/snmp.h>
#include <net/sock.h>
#include <net/tcp.h>
-#define DCCP_DEBUG
-
-#ifdef DCCP_DEBUG
+#ifdef CONFIG_IP_DCCP_DEBUG
extern int dccp_debug;
#define dccp_pr_debug(format, a...) \
@@ -426,7 +425,7 @@
extern void dccp_ackpkts_check_rcv_ackno(struct dccp_ackpkts *ap,
struct sock *sk, u64 ackno);
-#ifdef DCCP_DEBUG
+#ifdef CONFIG_IP_DCCP_DEBUG
extern void dccp_ackvector_print(const u64 ackno,
const unsigned char *vector, int len);
extern void dccp_ackpkts_print(const struct dccp_ackpkts *ap);
diff --git a/net/dccp/options.c b/net/dccp/options.c
index 68d6614..fc363aa 100644
--- a/net/dccp/options.c
+++ b/net/dccp/options.c
@@ -58,7 +58,7 @@
int dccp_parse_options(struct sock *sk, struct sk_buff *skb)
{
struct dccp_sock *dp = dccp_sk(sk);
-#ifdef DCCP_DEBUG
+#ifdef CONFIG_IP_DCCP_DEBUG
const char *debug_prefix = dp->dccps_role == DCCP_ROLE_CLIENT ?
"CLIENT rx opt: " : "server rx opt: ";
#endif
@@ -303,7 +303,7 @@
struct sk_buff *skb,
u32 elapsed_time)
{
-#ifdef DCCP_DEBUG
+#ifdef CONFIG_IP_DCCP_DEBUG
struct dccp_sock *dp = dccp_sk(sk);
const char *debug_prefix = dp->dccps_role == DCCP_ROLE_CLIENT ?
"CLIENT TX opt: " : "server TX opt: ";
@@ -341,7 +341,7 @@
static void dccp_insert_option_ack_vector(struct sock *sk, struct sk_buff *skb)
{
struct dccp_sock *dp = dccp_sk(sk);
-#ifdef DCCP_DEBUG
+#ifdef CONFIG_IP_DCCP_DEBUG
const char *debug_prefix = dp->dccps_role == DCCP_ROLE_CLIENT ?
"CLIENT TX opt: " : "server TX opt: ";
#endif
@@ -425,7 +425,7 @@
struct sk_buff *skb)
{
struct dccp_sock *dp = dccp_sk(sk);
-#ifdef DCCP_DEBUG
+#ifdef CONFIG_IP_DCCP_DEBUG
const char *debug_prefix = dp->dccps_role == DCCP_ROLE_CLIENT ?
"CLIENT TX opt: " : "server TX opt: ";
#endif
@@ -504,7 +504,7 @@
struct dccp_ackpkts *ap = kmalloc(sizeof(*ap) + len, priority);
if (ap != NULL) {
-#ifdef DCCP_DEBUG
+#ifdef CONFIG_IP_DCCP_DEBUG
memset(ap->dccpap_buf, 0xFF, len);
#endif
ap->dccpap_buf_len = len;
@@ -526,7 +526,7 @@
void dccp_ackpkts_free(struct dccp_ackpkts *ap)
{
if (ap != NULL) {
-#ifdef DCCP_DEBUG
+#ifdef CONFIG_IP_DCCP_DEBUG
memset(ap, 0xFF, sizeof(*ap) + ap->dccpap_buf_len);
#endif
kfree(ap);
@@ -680,7 +680,7 @@
return -EILSEQ;
}
-#ifdef DCCP_DEBUG
+#ifdef CONFIG_IP_DCCP_DEBUG
void dccp_ackvector_print(const u64 ackno, const unsigned char *vector,
int len)
{
@@ -735,7 +735,7 @@
return;
if (ackno == ap->dccpap_ack_seqno) {
-#ifdef DCCP_DEBUG
+#ifdef CONFIG_IP_DCCP_DEBUG
struct dccp_sock *dp = dccp_sk(sk);
const char *debug_prefix = dp->dccps_role == DCCP_ROLE_CLIENT ?
"CLIENT rx ack: " : "server rx ack: ";
@@ -794,7 +794,7 @@
/* dccp_pr_debug_cat("yes\n"); */
if (state != DCCP_ACKPKTS_STATE_NOT_RECEIVED) {
-#ifdef DCCP_DEBUG
+#ifdef CONFIG_IP_DCCP_DEBUG
struct dccp_sock *dp = dccp_sk(sk);
const char *debug_prefix =
dp->dccps_role == DCCP_ROLE_CLIENT ?
diff --git a/net/dccp/proto.c b/net/dccp/proto.c
index ed0bf58..be06692 100644
--- a/net/dccp/proto.c
+++ b/net/dccp/proto.c
@@ -503,12 +503,16 @@
return rc;
}
-static void __exit dccp_ctl_sock_exit(void)
+#ifdef CONFIG_IP_DCCP_UNLOAD_HACK
+void dccp_ctl_sock_exit(void)
{
if (dccp_ctl_socket != NULL)
sock_release(dccp_ctl_socket);
}
+EXPORT_SYMBOL_GPL(dccp_ctl_sock_exit);
+#endif
+
static int __init init_dccp_v4_mibs(void)
{
int rc = -ENOMEM;
@@ -655,19 +659,21 @@
static void __exit dccp_fini(void)
{
- dccp_ctl_sock_exit();
-
inet_unregister_protosw(&dccp_v4_protosw);
if (inet_del_protocol(&dccp_protocol, IPPROTO_DCCP) < 0)
printk(dccp_del_proto_err_msg);
- /* Free the control endpoint. */
- sock_release(dccp_ctl_socket);
-
- proto_unregister(&dccp_v4_prot);
-
+ free_percpu(dccp_statistics[0]);
+ free_percpu(dccp_statistics[1]);
+ free_pages((unsigned long)dccp_hashinfo.bhash,
+ get_order(dccp_hashinfo.bhash_size *
+ sizeof(struct inet_bind_hashbucket)));
+ free_pages((unsigned long)dccp_hashinfo.ehash,
+ get_order(dccp_hashinfo.ehash_size *
+ sizeof(struct inet_ehash_bucket)));
kmem_cache_destroy(dccp_hashinfo.bind_bucket_cachep);
+ proto_unregister(&dccp_v4_prot);
}
module_init(dccp_init);