* [PATCH 05/12] netfilter: udp proto sysctl support for net namespace
From: Gao feng @ 2012-04-17 2:56 UTC (permalink / raw)
To: pablo; +Cc: netfilter-devel, netdev, ebiederm, serge.hallyn, dlezcano,
Gao feng
In-Reply-To: <1334631383-12326-1-git-send-email-gaofeng@cn.fujitsu.com>
add and export four functions nf_conntrack_proto_ipv[4,6]_udp_[init,fini]
for the nf_conntrack_ipv[4,6] modules.
modify the udp_timeouts to net->ct.proto.sysctl_udp_timeouts
---
net/netfilter/nf_conntrack_proto_udp.c | 160 +++++++++++++++++++++++++++-----
1 files changed, 138 insertions(+), 22 deletions(-)
diff --git a/net/netfilter/nf_conntrack_proto_udp.c b/net/netfilter/nf_conntrack_proto_udp.c
index a9073dc..8e2935a 100644
--- a/net/netfilter/nf_conntrack_proto_udp.c
+++ b/net/netfilter/nf_conntrack_proto_udp.c
@@ -19,18 +19,13 @@
#include <linux/netfilter.h>
#include <linux/netfilter_ipv4.h>
#include <linux/netfilter_ipv6.h>
+#include <linux/netfilter/nf_conntrack_udp.h>
#include <net/netfilter/nf_conntrack_l4proto.h>
#include <net/netfilter/nf_conntrack_ecache.h>
#include <net/netfilter/nf_log.h>
#include <net/netfilter/ipv4/nf_conntrack_ipv4.h>
#include <net/netfilter/ipv6/nf_conntrack_ipv6.h>
-enum udp_conntrack {
- UDP_CT_UNREPLIED,
- UDP_CT_REPLIED,
- UDP_CT_MAX
-};
-
static unsigned int udp_timeouts[UDP_CT_MAX] = {
[UDP_CT_UNREPLIED] = 30*HZ,
[UDP_CT_REPLIED] = 180*HZ,
@@ -73,7 +68,7 @@ static int udp_print_tuple(struct seq_file *s,
static unsigned int *udp_get_timeouts(struct net *net)
{
- return udp_timeouts;
+ return net->ct.proto.sysctl_udp_timeouts;
}
/* Returns verdict for packet, and may modify conntracktype */
@@ -199,8 +194,6 @@ udp_timeout_nla_policy[CTA_TIMEOUT_UDP_MAX+1] = {
#endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */
#ifdef CONFIG_SYSCTL
-static unsigned int udp_sysctl_table_users;
-static struct ctl_table_header *udp_sysctl_header;
static struct ctl_table udp_sysctl_table[] = {
{
.procname = "nf_conntrack_udp_timeout",
@@ -266,14 +259,6 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_udp4 __read_mostly =
.nla_policy = udp_timeout_nla_policy,
},
#endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */
-#ifdef CONFIG_SYSCTL
- .ctl_table_users = &udp_sysctl_table_users,
- .ctl_table_header = &udp_sysctl_header,
- .ctl_table = udp_sysctl_table,
-#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT
- .ctl_compat_table = udp_compat_sysctl_table,
-#endif
-#endif
};
EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_udp4);
@@ -304,10 +289,141 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_udp6 __read_mostly =
.nla_policy = udp_timeout_nla_policy,
},
#endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */
-#ifdef CONFIG_SYSCTL
- .ctl_table_users = &udp_sysctl_table_users,
- .ctl_table_header = &udp_sysctl_header,
- .ctl_table = udp_sysctl_table,
-#endif
};
EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_udp6);
+
+static int nf_conntrack_proto_udp_net_init(struct net *net)
+{
+ struct ctl_table *table;
+ int i, ret = 0;
+
+#ifdef CONFIG_SYSCTL
+ if (!net->ct.proto.udp_sysctl_header) {
+ net->ct.proto.udp_table_users = 0;
+ for (i = 0; i < UDP_CT_MAX; i++)
+ net->ct.proto.sysctl_udp_timeouts[i] = udp_timeouts[i];
+ table = kmemdup(udp_sysctl_table,
+ sizeof(udp_sysctl_table),
+ GFP_KERNEL);
+ if (!table)
+ return -ENOMEM;
+ table[0].data = &net->ct.proto.
+ sysctl_udp_timeouts[UDP_CT_UNREPLIED];
+ table[1].data = &net->ct.proto.
+ sysctl_udp_timeouts[UDP_CT_REPLIED];
+ } else
+ table = net->ct.proto.udp_sysctl_header->ctl_table_arg;
+
+ ret = nf_ct_register_net_sysctl(net,
+ &net->ct.proto.udp_sysctl_header,
+ nf_net_netfilter_sysctl_path,
+ table,
+ &net->ct.proto.udp_table_users);
+ if (ret < 0) {
+ printk(KERN_ERR
+ "nf_conntrack_proto_udp:"
+ " can't register to sysctl.\n");
+ goto out_register;
+ }
+ return 0;
+out_register:
+ if (!net->ct.proto.udp_sysctl_header)
+ kfree(table);
+#else
+ for (i = 0; i < UDP_CT_MAX; i++)
+ net->ct.proto.sysctl_udp_timeouts[i] = udp_timeouts[i];
+#endif
+ return ret;
+}
+
+static void nf_conntrack_proto_udp_net_fini(struct net *net)
+{
+#ifdef CONFIG_SYSCTL
+ struct ctl_table *table;
+ table = net->ct.proto.udp_sysctl_header->ctl_table_arg;
+
+ nf_ct_unregister_net_sysctl(&net->ct.proto.udp_sysctl_header,
+ table,
+ &net->ct.proto.udp_table_users);
+#endif
+}
+
+static int nf_conntrack_proto_udp_compat_init(struct net *net)
+{
+ int ret = 0;
+#ifdef CONFIG_SYSCTL
+#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT
+ struct ctl_table *compat_table;
+ compat_table = kmemdup(udp_compat_sysctl_table,
+ sizeof(udp_compat_sysctl_table),
+ GFP_KERNEL);
+ if (!compat_table)
+ return -ENOMEM;
+ compat_table[0].data = &net->ct.proto.
+ sysctl_udp_timeouts[UDP_CT_UNREPLIED];
+ compat_table[1].data = &net->ct.proto.
+ sysctl_udp_timeouts[UDP_CT_REPLIED];
+
+ ret = nf_ct_register_net_sysctl(net,
+ &net->ct.proto.udp_compat_header,
+ nf_net_ipv4_netfilter_sysctl_path,
+ compat_table,
+ NULL);
+ if (ret < 0) {
+ printk(KERN_ERR
+ "nf_conntrack_proto_udp:"
+ " can't register to compat sysctl.\n");
+ goto out_register;
+ }
+ return 0;
+out_register:
+ kfree(compat_table);
+#endif
+#endif
+ return ret;
+}
+
+static void nf_conntrack_proto_udp_compat_fini(struct net *net)
+{
+#ifdef CONFIG_SYSCTL
+#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT
+ struct ctl_table *compat_table;
+ compat_table = net->ct.proto.udp_compat_header->ctl_table_arg;
+ nf_ct_unregister_net_sysctl(&net->ct.proto.udp_compat_header,
+ compat_table,
+ NULL);
+#endif
+#endif
+}
+
+int nf_conntrack_proto_ipv4_udp_init(struct net *net)
+{
+ int ret = 0;
+ ret = nf_conntrack_proto_udp_net_init(net);
+ if (ret < 0)
+ return ret;
+ ret = nf_conntrack_proto_udp_compat_init(net);
+ if (ret < 0)
+ nf_conntrack_proto_udp_net_fini(net);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(nf_conntrack_proto_ipv4_udp_init);
+
+void nf_conntrack_proto_ipv4_udp_fini(struct net *net)
+{
+ nf_conntrack_proto_udp_compat_fini(net);
+ nf_conntrack_proto_udp_net_fini(net);
+}
+EXPORT_SYMBOL_GPL(nf_conntrack_proto_ipv4_udp_fini);
+
+int nf_conntrack_proto_ipv6_udp_init(struct net *net)
+{
+ return nf_conntrack_proto_udp_net_init(net);
+}
+EXPORT_SYMBOL_GPL(nf_conntrack_proto_ipv6_udp_init);
+
+void nf_conntrack_proto_ipv6_udp_fini(struct net *net)
+{
+ return nf_conntrack_proto_udp_net_fini(net);
+}
+EXPORT_SYMBOL_GPL(nf_conntrack_proto_ipv6_udp_fini);
--
1.7.7.6
^ permalink raw reply related
* [PATCH 06/12] netfilter: icmp proto sysctl support for net namespace
From: Gao feng @ 2012-04-17 2:56 UTC (permalink / raw)
To: pablo; +Cc: netfilter-devel, netdev, ebiederm, serge.hallyn, dlezcano,
Gao feng
In-Reply-To: <1334631383-12326-1-git-send-email-gaofeng@cn.fujitsu.com>
add and export functions nf_conntrack_proto_ipv4_icmp_[init,fini]
for the nf_conntrack_ipv4 modules.
modify the nf_ct_icmp_timeout to net->ct.proto.sysctl_icmp_timeout
Signed-off-by: Gao feng <gaofeng@cn.fujitsu.com>
---
net/ipv4/netfilter/nf_conntrack_proto_icmp.c | 116 ++++++++++++++++++++++++--
1 files changed, 108 insertions(+), 8 deletions(-)
diff --git a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c
index 7cbe9cb..fa827ee 100644
--- a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c
+++ b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c
@@ -12,6 +12,7 @@
#include <linux/in.h>
#include <linux/icmp.h>
#include <linux/seq_file.h>
+#include <linux/module.h>
#include <net/ip.h>
#include <net/checksum.h>
#include <linux/netfilter_ipv4.h>
@@ -77,7 +78,7 @@ static int icmp_print_tuple(struct seq_file *s,
static unsigned int *icmp_get_timeouts(struct net *net)
{
- return &nf_ct_icmp_timeout;
+ return &net->ct.proto.sysctl_icmp_timeout;
}
/* Returns verdict for packet, or -1 for invalid. */
@@ -308,11 +309,10 @@ icmp_timeout_nla_policy[CTA_TIMEOUT_ICMP_MAX+1] = {
#endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */
#ifdef CONFIG_SYSCTL
-static struct ctl_table_header *icmp_sysctl_header;
static struct ctl_table icmp_sysctl_table[] = {
{
.procname = "nf_conntrack_icmp_timeout",
- .data = &nf_ct_icmp_timeout,
+ .data = &init_net.ct.proto.sysctl_icmp_timeout,
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = proc_dointvec_jiffies,
@@ -323,7 +323,7 @@ static struct ctl_table icmp_sysctl_table[] = {
static struct ctl_table icmp_compat_sysctl_table[] = {
{
.procname = "ip_conntrack_icmp_timeout",
- .data = &nf_ct_icmp_timeout,
+ .data = &init_net.ct.proto.sysctl_icmp_timeout,
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = proc_dointvec_jiffies,
@@ -362,11 +362,111 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_icmp __read_mostly =
.nla_policy = icmp_timeout_nla_policy,
},
#endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */
+};
+
+static int nf_conntrack_proto_icmp_net_init(struct net *net)
+{
+ struct ctl_table *table;
+ int ret = 0;
+
+ net->ct.proto.sysctl_icmp_timeout = nf_ct_icmp_timeout;
+#ifdef CONFIG_SYSCTL
+ table = kmemdup(icmp_sysctl_table,
+ sizeof(icmp_sysctl_table),
+ GFP_KERNEL);
+ if (!table)
+ return -ENOMEM;
+ table[0].data = &net->ct.proto.sysctl_icmp_timeout;
+
+ ret = nf_ct_register_net_sysctl(net,
+ &net->ct.proto.icmp_sysctl_header,
+ nf_net_netfilter_sysctl_path,
+ table,
+ NULL);
+ if (ret < 0) {
+ printk(KERN_ERR
+ "nf_conntrack icmp: can't register to sysctl.\n");
+ goto out_register;
+ }
+ return 0;
+out_register:
+ kfree(table);
+#endif
+ return ret;
+}
+
+static void nf_conntrack_proto_icmp_net_fini(struct net *net)
+{
+#ifdef CONFIG_SYSCTL
+ struct ctl_table *table;
+ table = net->ct.proto.icmp_sysctl_header->ctl_table_arg;
+
+ nf_ct_unregister_net_sysctl(&net->ct.proto.icmp_sysctl_header,
+ table,
+ NULL);
+#endif
+}
+
+static int nf_conntrack_proto_icmp_compat_init(struct net *net)
+{
+ int ret = 0;
#ifdef CONFIG_SYSCTL
- .ctl_table_header = &icmp_sysctl_header,
- .ctl_table = icmp_sysctl_table,
#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT
- .ctl_compat_table = icmp_compat_sysctl_table,
+ struct ctl_table *compat_table;
+ compat_table = kmemdup(icmp_compat_sysctl_table,
+ sizeof(icmp_compat_sysctl_table),
+ GFP_KERNEL);
+ if (!compat_table)
+ return -ENOMEM;
+ compat_table[0].data = &net->ct.proto.sysctl_icmp_timeout;
+
+ ret = nf_ct_register_net_sysctl(net,
+ &net->ct.proto.icmp_compat_header,
+ nf_net_ipv4_netfilter_sysctl_path,
+ compat_table,
+ NULL);
+ if (ret < 0) {
+ printk(KERN_ERR
+ "nf_conntrack icmp: register compat sysctl failed.\n");
+ goto out_register;
+ }
+ return 0;
+out_register:
+ kfree(compat_table);
#endif
#endif
-};
+ return ret;
+}
+
+static void nf_conntrack_proto_icmp_compat_fini(struct net *net)
+{
+#ifdef CONFIG_SYSCTL
+#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT
+ struct ctl_table *compat_table;
+ compat_table = net->ct.proto.icmp_compat_header->ctl_table_arg;
+ nf_ct_unregister_net_sysctl(&net->ct.proto.icmp_compat_header,
+ compat_table,
+ NULL);
+#endif
+#endif
+}
+
+int nf_conntrack_proto_ipv4_icmp_init(struct net *net)
+{
+ int ret = 0;
+ ret = nf_conntrack_proto_icmp_net_init(net);
+ if (ret < 0)
+ return ret;
+ ret = nf_conntrack_proto_icmp_compat_init(net);
+ if (ret < 0)
+ nf_conntrack_proto_icmp_net_fini(net);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(nf_conntrack_proto_ipv4_icmp_init);
+
+void nf_conntrack_proto_ipv4_icmp_fini(struct net *net)
+{
+ nf_conntrack_proto_icmp_compat_fini(net);
+ nf_conntrack_proto_icmp_net_fini(net);
+}
+EXPORT_SYMBOL_GPL(nf_conntrack_proto_ipv4_icmp_fini);
--
1.7.7.6
^ permalink raw reply related
* [PATCH 03/12] netfilter: generic proto sysctl support for net namespace
From: Gao feng @ 2012-04-17 2:56 UTC (permalink / raw)
To: pablo; +Cc: netfilter-devel, netdev, ebiederm, serge.hallyn, dlezcano,
Gao feng
In-Reply-To: <1334631383-12326-1-git-send-email-gaofeng@cn.fujitsu.com>
register the generic proto's sysctl in pernet_operations.init.
and use net->ct.proto.sysctl_generic_timeout replaces nf_ct_generic_timeout.
in the after patch,the timeout_nlattr_to_obj will be modified too.
Signed-off-by: Gao feng <gaofeng@cn.fujitsu.com>
---
net/netfilter/nf_conntrack_core.c | 6 ++
net/netfilter/nf_conntrack_proto_generic.c | 93 +++++++++++++++++++++++++---
2 files changed, 91 insertions(+), 8 deletions(-)
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c
index 729f157..bf11dd6 100644
--- a/net/netfilter/nf_conntrack_core.c
+++ b/net/netfilter/nf_conntrack_core.c
@@ -1358,6 +1358,7 @@ static void nf_conntrack_cleanup_net(struct net *net)
nf_conntrack_tstamp_fini(net);
nf_conntrack_acct_fini(net);
nf_conntrack_expect_fini(net);
+ nf_conntrack_proto_generic_net_fini(net);
kmem_cache_destroy(net->ct.nf_conntrack_cachep);
kfree(net->ct.slabname);
free_percpu(net->ct.stat);
@@ -1573,6 +1574,9 @@ static int nf_conntrack_init_net(struct net *net)
printk(KERN_ERR "Unable to create nf_conntrack_hash\n");
goto err_hash;
}
+ ret = nf_conntrack_proto_generic_net_init(net);
+ if (ret < 0)
+ goto err_generic;
ret = nf_conntrack_expect_init(net);
if (ret < 0)
goto err_expect;
@@ -1600,6 +1604,8 @@ err_tstamp:
err_acct:
nf_conntrack_expect_fini(net);
err_expect:
+ nf_conntrack_proto_generic_net_fini(net);
+err_generic:
nf_ct_free_hashtable(net->ct.hash, net->ct.htable_size);
err_hash:
kmem_cache_destroy(net->ct.nf_conntrack_cachep);
diff --git a/net/netfilter/nf_conntrack_proto_generic.c b/net/netfilter/nf_conntrack_proto_generic.c
index 835e24c..0d4545b 100644
--- a/net/netfilter/nf_conntrack_proto_generic.c
+++ b/net/netfilter/nf_conntrack_proto_generic.c
@@ -42,7 +42,7 @@ static int generic_print_tuple(struct seq_file *s,
static unsigned int *generic_get_timeouts(struct net *net)
{
- return &nf_ct_generic_timeout;
+ return &(net->ct.proto.sysctl_generic_timeout);
}
/* Returns verdict for packet, or -1 for invalid. */
@@ -105,11 +105,10 @@ generic_timeout_nla_policy[CTA_TIMEOUT_GENERIC_MAX+1] = {
#endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */
#ifdef CONFIG_SYSCTL
-static struct ctl_table_header *generic_sysctl_header;
static struct ctl_table generic_sysctl_table[] = {
{
.procname = "nf_conntrack_generic_timeout",
- .data = &nf_ct_generic_timeout,
+ .data = &init_net.ct.proto.sysctl_generic_timeout,
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = proc_dointvec_jiffies,
@@ -120,7 +119,7 @@ static struct ctl_table generic_sysctl_table[] = {
static struct ctl_table generic_compat_sysctl_table[] = {
{
.procname = "ip_conntrack_generic_timeout",
- .data = &nf_ct_generic_timeout,
+ .data = &init_net.ct.proto.sysctl_generic_timeout,
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = proc_dointvec_jiffies,
@@ -150,11 +149,89 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_generic __read_mostly =
.nla_policy = generic_timeout_nla_policy,
},
#endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */
+};
+
+int nf_conntrack_proto_generic_net_init(struct net *net)
+{
+ struct ctl_table *table;
+ int ret = 0;
#ifdef CONFIG_SYSCTL
- .ctl_table_header = &generic_sysctl_header,
- .ctl_table = generic_sysctl_table,
#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT
- .ctl_compat_table = generic_compat_sysctl_table,
+ struct ctl_table *compat_table;
#endif
#endif
-};
+ net->ct.proto.sysctl_generic_timeout = nf_ct_generic_timeout;
+#ifdef CONFIG_SYSCTL
+ table = kmemdup(generic_sysctl_table,
+ sizeof(generic_sysctl_table),
+ GFP_KERNEL);
+ if (!table)
+ return -ENOMEM;
+
+ table[0].data = &net->ct.proto.sysctl_generic_timeout;
+
+ ret = nf_ct_register_net_sysctl(net,
+ &net->ct.proto.generic_sysctl_header,
+ nf_net_netfilter_sysctl_path,
+ table,
+ NULL);
+ if (ret < 0) {
+ printk(KERN_ERR
+ "nf_conntrack_proto_generic:"
+ " can't register to sysctl.\n");
+ kfree(table);
+ return ret;
+ }
+#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT
+ compat_table = kmemdup(generic_compat_sysctl_table,
+ sizeof(generic_compat_sysctl_table),
+ GFP_KERNEL);
+ if (!compat_table) {
+ ret = -ENOMEM;
+ goto out_compat;
+ }
+ compat_table[0].data = &net->ct.proto.sysctl_generic_timeout;
+ ret = nf_ct_register_net_sysctl(net,
+ &net->ct.proto.generic_compat_header,
+ nf_net_ipv4_netfilter_sysctl_path,
+ compat_table,
+ NULL);
+ if (ret < 0) {
+ printk(KERN_ERR
+ "nf_conntrack_proto_generic:"
+ " can't register to compat sysctl.\n");
+ goto out_compat_register;
+ }
+#endif
+ return 0;
+#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT
+out_compat_register:
+ kfree(compat_table);
+out_compat:
+ nf_ct_unregister_net_sysctl(&net->ct.proto.generic_sysctl_header,
+ table,
+ NULL);
+#endif
+#endif
+ return ret;
+}
+
+void nf_conntrack_proto_generic_net_fini(struct net *net)
+{
+#ifdef CONFIG_SYSCTL
+ struct ctl_table *table;
+#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT
+ struct ctl_table *compat_table;
+#endif
+ table = net->ct.proto.generic_sysctl_header->ctl_table_arg;
+ nf_ct_unregister_net_sysctl(&net->ct.proto.generic_sysctl_header,
+ table,
+ NULL);
+#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT
+ compat_table = net->ct.proto.generic_compat_header->ctl_table_arg;
+ nf_ct_unregister_net_sysctl(&net->ct.proto.generic_compat_header,
+ compat_table,
+ NULL);
+#endif
+#endif
+}
--
1.7.7.6
^ permalink raw reply related
* [PATCH 07/12] netfilter: icmpv6 proto sysctl support for net
From: Gao feng @ 2012-04-17 2:56 UTC (permalink / raw)
To: pablo; +Cc: netfilter-devel, netdev, ebiederm, serge.hallyn, dlezcano,
Gao feng
In-Reply-To: <1334631383-12326-1-git-send-email-gaofeng@cn.fujitsu.com>
add and export functions nf_conntrack_proto_icmpv6_net_[init,fini]
for the nf_conntrack_ipv6 modules.
modify the nf_ct_icmpv6_timeout to net->ct.proto.sysctl_icmpv6_timeout
Signed-off-by: Gao feng <gaofeng@cn.fujitsu.com>
---
net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c | 54 +++++++++++++++++++++---
1 files changed, 48 insertions(+), 6 deletions(-)
diff --git a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c
index 92cc9f2..ef33f31 100644
--- a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c
+++ b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c
@@ -90,7 +90,7 @@ static int icmpv6_print_tuple(struct seq_file *s,
static unsigned int *icmpv6_get_timeouts(struct net *net)
{
- return &nf_ct_icmpv6_timeout;
+ return &net->ct.proto.sysctl_icmpv6_timeout;
}
/* Returns verdict for packet, or -1 for invalid. */
@@ -315,11 +315,10 @@ icmpv6_timeout_nla_policy[CTA_TIMEOUT_ICMPV6_MAX+1] = {
#endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */
#ifdef CONFIG_SYSCTL
-static struct ctl_table_header *icmpv6_sysctl_header;
static struct ctl_table icmpv6_sysctl_table[] = {
{
.procname = "nf_conntrack_icmpv6_timeout",
- .data = &nf_ct_icmpv6_timeout,
+ .data = &init_net.ct.proto.sysctl_icmpv6_timeout,
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = proc_dointvec_jiffies,
@@ -355,8 +354,51 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_icmpv6 __read_mostly =
.nla_policy = icmpv6_timeout_nla_policy,
},
#endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */
+};
+
+int nf_conntrack_proto_icmpv6_net_init(struct net *net)
+{
+ struct ctl_table *table;
+ int ret = 0;
+
+ net->ct.proto.sysctl_icmpv6_timeout = nf_ct_icmpv6_timeout;
+
#ifdef CONFIG_SYSCTL
- .ctl_table_header = &icmpv6_sysctl_header,
- .ctl_table = icmpv6_sysctl_table,
+ table = kmemdup(icmpv6_sysctl_table,
+ sizeof(icmpv6_sysctl_table),
+ GFP_KERNEL);
+ if (!table)
+ return -ENOMEM;
+ table[0].data = &net->ct.proto.sysctl_icmpv6_timeout;
+
+ ret = nf_ct_register_net_sysctl(net,
+ &net->ct.proto.icmpv6_sysctl_header,
+ nf_net_netfilter_sysctl_path,
+ table,
+ NULL);
+ if (ret < 0) {
+ printk(KERN_ERR
+ "nf_conntrack_proto_icmpv6:"
+ " can't register to sysctl.\n");
+ goto out_register;
+ }
+ return 0;
+out_register:
+ kfree(table);
#endif
-};
+ return ret;
+}
+EXPORT_SYMBOL_GPL(nf_conntrack_proto_icmpv6_net_init);
+
+void nf_conntrack_proto_icmpv6_net_fini(struct net *net)
+{
+#ifdef CONFIG_SYSCTL
+ struct ctl_table *table;
+ table = net->ct.proto.icmpv6_sysctl_header->ctl_table_arg;
+
+ nf_ct_unregister_net_sysctl(&net->ct.proto.icmpv6_sysctl_header,
+ table, NULL);
+#endif
+}
+EXPORT_SYMBOL_GPL(nf_conntrack_proto_icmpv6_net_fini);
+
--
1.7.7.6
^ permalink raw reply related
* [PATCH 00/12] add namespace support for netfilter protos
From: Gao feng @ 2012-04-17 2:56 UTC (permalink / raw)
To: pablo; +Cc: netfilter-devel, netdev, ebiederm, serge.hallyn, dlezcano,
Gao feng
Currently the sysctl of netfilter proto is not isolated, so when
changing proto's sysctl in container will cause the host's sysctl
be changed too. it's not expected.
This patch set adds the namespace support for netfilter protos.
impletement four pernet_operations to register sysctl,and disable
register sysctl when protos are registered.
nf_conntrack_net_proto_ipv4_ops is used to register tcp4(compat),
udp4(compat),icmp(compat),ipv4(compat).
nf_conntrack_net_proto_ipv6_ops is used to register tcp6,udp6 and
icmpv6.
nf_conntrack_net_proto_sctp_ops is used to register sctp4(compat)
and sctp6.
nf_conntrack_net_proto_udplite_ops is used to register udplite4
and udplite6
these operations will be registered when module be loaded.
And this will break the cttimeout, because timeout_nlattr_to_obj
function use the orig timeout(such as tcp_timeouts) to set timeouts.
I will fix this in my next patch.
Gao feng (12):
netfilter: add struct netns_ct_proto to support netfilter namespace
netfilter: don't register sysctl when register proto
netfilter: generic proto sysctl support for net namespace
netfilter: tcp proto sysctl support for net namespace
netfilter: udp proto sysctl support for net namespace
netfilter: icmp proto sysctl support for net namespace
netfilter: icmpv6 proto sysctl support for net
netfilter: ipv4 sysctl support for net namespace
netfilter: ipv6 sysctl support for net namespace
netfilter: sctp proto sysctl support for net namespace
netfilter: udplite proto sysctl support for net
netfilter: export necessary function for generic proto
include/linux/netfilter/nf_conntrack_udp.h | 10 +
include/linux/netfilter/nf_conntrack_udplite.h | 10 +
include/net/netfilter/nf_conntrack_core.h | 3 +
include/net/netfilter/nf_conntrack_l3proto.h | 6 -
include/net/netfilter/nf_conntrack_l4proto.h | 38 +++-
include/net/netns/conntrack.h | 37 ++++
net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c | 96 ++++++++-
net/ipv4/netfilter/nf_conntrack_proto_icmp.c | 116 +++++++++-
net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c | 48 ++++
net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c | 54 ++++-
net/netfilter/nf_conntrack_core.c | 6 +
net/netfilter/nf_conntrack_proto.c | 109 ++--------
net/netfilter/nf_conntrack_proto_generic.c | 93 ++++++++-
net/netfilter/nf_conntrack_proto_sctp.c | 205 +++++++++++++++---
net/netfilter/nf_conntrack_proto_tcp.c | 275 ++++++++++++++++++++----
net/netfilter/nf_conntrack_proto_udp.c | 160 ++++++++++++--
net/netfilter/nf_conntrack_proto_udplite.c | 83 ++++++--
17 files changed, 1096 insertions(+), 253 deletions(-)
create mode 100644 include/linux/netfilter/nf_conntrack_udp.h
create mode 100644 include/linux/netfilter/nf_conntrack_udplite.h
--
1.7.7.6
^ permalink raw reply
* [PATCH 09/12] netfilter: ipv6 sysctl support for net namespace
From: Gao feng @ 2012-04-17 2:56 UTC (permalink / raw)
To: pablo; +Cc: netfilter-devel, netdev, ebiederm, serge.hallyn, dlezcano,
Gao feng
In-Reply-To: <1334631383-12326-1-git-send-email-gaofeng@cn.fujitsu.com>
register pernet_operations nf_conntrack_net_proto_ipv6_ops
when loading nf_conntrack_ipv6 module,and unregister it when
removing.
Signed-off-by: Gao feng <gaofeng@cn.fujitsu.com>
---
net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c | 48 ++++++++++++++++++++++++
1 files changed, 48 insertions(+), 0 deletions(-)
diff --git a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
index 4111050..8c0456c 100644
--- a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
+++ b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
@@ -333,6 +333,43 @@ MODULE_ALIAS("nf_conntrack-" __stringify(AF_INET6));
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Yasuyuki KOZAKAI @USAGI <yasuyuki.kozakai@toshiba.co.jp>");
+static int nf_conntrack_net_proto_ipv6_init(struct net *net)
+{
+ int ret;
+
+ ret = nf_conntrack_proto_ipv6_tcp_init(net);
+ if (ret < 0)
+ return ret;
+
+ ret = nf_conntrack_proto_ipv6_udp_init(net);
+ if (ret < 0)
+ goto cleanup_tcp;
+
+ ret = nf_conntrack_proto_icmpv6_net_init(net);
+ if (ret < 0)
+ goto cleanup_udp;
+ return 0;
+ cleanup_udp:
+ nf_conntrack_proto_ipv6_udp_fini(net);
+
+ cleanup_tcp:
+ nf_conntrack_proto_ipv6_tcp_fini(net);
+
+ return ret;
+}
+
+static void nf_conntrack_net_proto_ipv6_fini(struct net *net)
+{
+ nf_conntrack_proto_icmpv6_net_fini(net);
+ nf_conntrack_proto_ipv6_udp_fini(net);
+ nf_conntrack_proto_ipv6_tcp_fini(net);
+}
+
+static struct pernet_operations nf_conntrack_net_proto_ipv6_ops = {
+ .init = nf_conntrack_net_proto_ipv6_init,
+ .exit = nf_conntrack_net_proto_ipv6_fini,
+};
+
static int __init nf_conntrack_l3proto_ipv6_init(void)
{
int ret = 0;
@@ -371,8 +408,18 @@ static int __init nf_conntrack_l3proto_ipv6_init(void)
"hook.\n");
goto cleanup_ipv6;
}
+
+ ret = register_pernet_subsys(&nf_conntrack_net_proto_ipv6_ops);
+ if (ret < 0) {
+ pr_err("nf_conntrack_ipv6: can't register pernet subsys.\n");
+ goto cleanup_hooks;
+ }
+
return ret;
+ cleanup_hooks:
+ nf_unregister_hooks(ipv6_conntrack_ops,
+ ARRAY_SIZE(ipv6_conntrack_ops));
cleanup_ipv6:
nf_conntrack_l3proto_unregister(&nf_conntrack_l3proto_ipv6);
cleanup_icmpv6:
@@ -387,6 +434,7 @@ static int __init nf_conntrack_l3proto_ipv6_init(void)
static void __exit nf_conntrack_l3proto_ipv6_fini(void)
{
synchronize_net();
+ unregister_pernet_subsys(&nf_conntrack_net_proto_ipv6_ops);
nf_unregister_hooks(ipv6_conntrack_ops, ARRAY_SIZE(ipv6_conntrack_ops));
nf_conntrack_l3proto_unregister(&nf_conntrack_l3proto_ipv6);
nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_icmpv6);
--
1.7.7.6
^ permalink raw reply related
* Re: [PATCH 6/6] vhost_net: don't poll on -EFAULT
From: Jason Wang @ 2012-04-17 3:27 UTC (permalink / raw)
To: Michael S. Tsirkin; +Cc: netdev, xma, davem, linux-kernel, ebiederm
In-Reply-To: <20120416133859.GB13190@redhat.com>
On 04/16/2012 09:39 PM, Michael S. Tsirkin wrote:
> On Mon, Apr 16, 2012 at 04:28:10PM +0800, Jason Wang wrote:
>> > On 04/16/2012 03:16 PM, Michael S. Tsirkin wrote:
>>> > >On Mon, Apr 16, 2012 at 02:08:33PM +0800, Jason Wang wrote:
>>>> > >>Currently, we restart tx polling unconditionally when sendmsg()
>>>> > >>fails. This would cause unnecessary wakeups of vhost wokers as it's
>>>> > >>only needed when the socket send buffer were exceeded.
>>> > >Why is this a problem?
>> >
>> > This issue is when guest driver is able to hit the -EFAULT, vhost
>> > discard the the descriptor and restart the polling. This would wake
>> > vhost thread and repeat the loop again which waste cpu.
> Does same thing happen if we get an error from copy from user?
>
Right, so do you think it makes sense that we only restart polling on
-EAGAIN or -ENOBUFS?
^ permalink raw reply
* Re: [PATCH 5/6] vhost_net: fix use after free of vq->ubufs
From: Jason Wang @ 2012-04-17 3:19 UTC (permalink / raw)
To: Michael S. Tsirkin; +Cc: netdev, xma, davem, linux-kernel, ebiederm
In-Reply-To: <20120416132841.GB13113@redhat.com>
On 04/16/2012 09:28 PM, Michael S. Tsirkin wrote:
> On Mon, Apr 16, 2012 at 02:08:25PM +0800, Jason Wang wrote:
>> When zerocopy socket is used, ubufs pointer were used in handle_tx()
>> without any validation. This would cause NULL pointer deference after
>> it has been freed in vhost_net_set_backend(). Fix this by check the
>> pointer before using it.
>>
>> Signed-off-by: Jason Wang<jasowang@redhat.com>
>
> OK so it's NULL dereference and not user after free :)
> Also could you clarify how does this happen pls?
> Don't we always initialize ubufs when vhost_sock_zcopy is set?
The problem happens when we want to disable backend. At this time ubufs
were assigned to NULL and it may be dereferenced by handle_tx():
BUG: unable to handle kernel NULL pointer dereference at (null)
IP: [<ffffffffa0474c57>] handle_tx+0x267/0x5c0 [vhost_net]
PGD 4230b1067 PUD 42227a067 PMD 0
Oops: 0000 [#1] SMP
CPU 7
Modules linked in: vhost_net ip6table_filter ip6_tables ebtable_nat
ebtables ipt_MASQUERADE iptable_nat nf_nat nf_conntrack_ipv4
nf_defrag_ipv4 xt_state nf_conntrack ipt_REJECT xt_CHECKSUM
iptable_mangle iptable_filter ip_tables nfsd lockd nfs_acl auth_rpcgss
sunrpc exportfs cpufreq_ondemand acpi_cpufreq freq_table mperf bridge
stp llc ipv6 tun kvm_intel kvm hp_wmi sparse_keymap rfkill coretemp
crc32c_intel ghash_clmulni_intel microcode serio_raw pcspkr sg iTCO_wdt
iTCO_vendor_support tg3 snd_hda_codec_realtek snd_hda_intel
snd_hda_codec snd_hwdep snd_seq snd_seq_device snd_pcm snd_timer snd
soundcore snd_page_alloc i7core_edac edac_core ixgbe dca mdio ext4
mbcache jbd2 sd_mod crc_t10dif sr_mod cdrom firewire_ohci firewire_core
crc_itu_t aesni_intel cryptd aes_x86_64 aes_generic mptsas mptscsih
mptbase scsi_transport_sas ahci libahci floppy nouveau ttm
drm_kms_helper drm i2c_core mxm_wmi video wmi dm_mirror dm_region_hash
dm_log dm_mod [last unloaded: vhost_net]
Pid: 3993, comm: vhost-3991 Not tainted 3.3.0+ #10 Hewlett-Packard HP
Z800 Workstation/0AECh
RIP: 0010:[<ffffffffa0474c57>] [<ffffffffa0474c57>]
handle_tx+0x267/0x5c0 [vhost_net]
RSP: 0018:ffff880220b41d90 EFLAGS: 00010286
RAX: 0000000000000000 RBX: ffff8804222242b0 RCX: 0000000000000000
RDX: 0000000000000000 RSI: 0000000000000000 RDI: 00007f5f495e6002
RBP: ffff880220b41e60 R08: 0000000000000000 R09: 0000000000000002
R10: 000000007fffffff R11: ffff8802246b7340 R12: ffff8804222243d8
R13: ffff8804222283d8 R14: 0000000004e20000 R15: ffff880422a1f690
FS: 0000000000000000(0000) GS:ffff88042fc60000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b
CR2: 0000000000000000 CR3: 0000000424786000 CR4: 00000000000027e0
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400
Process vhost-3991 (pid: 3993, threadinfo ffff880220b40000, task
ffff880222606a70)
Stack:
0000000000000000 0000000000000000 ffff880422220000 ffff880220b41df0
0000000000000007 ffff880200000000 0000000000000000 ffff8804222242b8
0000000000000000 0000000000000000 01ff880220b41fd8 ffff880422220000
Call Trace:
[<ffffffffa0474fc5>] handle_tx_net+0x15/0x20 [vhost_net]
[<ffffffffa0472cf4>] vhost_worker+0xe4/0x180 [vhost_net]
[<ffffffffa0472c10>] ? vhost_attach_cgroups_work+0x30/0x30 [vhost_net]
[<ffffffffa0472c10>] ? vhost_attach_cgroups_work+0x30/0x30 [vhost_net]
[<ffffffff8107096e>] kthread+0x9e/0xb0
[<ffffffff81516364>] kernel_thread_helper+0x4/0x10
[<ffffffff810708d0>] ? kthread_freezable_should_stop+0x70/0x70
[<ffffffff81516360>] ? gs_change+0x13/0x13
Code: 00 00 48 89 50 08 48 63 93 20 42 00 00 48 89 50 10 48 89 45 b0 48
c7 45 b8 08 00 00 00 48 8b 83 30 42 00 00 48 89 85 60 ff ff ff <8b> 00
85 c0 0f 84 1c 03 00 00 48 8b 85 60 ff ff ff f0 ff 00 8b
RIP [<ffffffffa0474c57>] handle_tx+0x267/0x5c0 [vhost_net]
RSP <ffff880220b41d90>
CR2: 0000000000000000
>
>> ---
>> drivers/vhost/net.c | 7 ++++++-
>> 1 files changed, 6 insertions(+), 1 deletions(-)
>>
>> diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c
>> index f0da2c3..29abd65 100644
>> --- a/drivers/vhost/net.c
>> +++ b/drivers/vhost/net.c
>> @@ -163,10 +163,15 @@ static void handle_tx(struct vhost_net *net)
>> mutex_lock(&vq->mutex);
>> vhost_disable_notify(&net->dev, vq);
>>
>> + zcopy = vhost_sock_zcopy(sock);
>> + if (zcopy&& !vq->ubufs) {
>> + mutex_unlock(&vq->mutex);
>> + return;
>> + }
>> +
>> if (wmem< sock->sk->sk_sndbuf / 2)
>> tx_poll_stop(net);
>> hdr_size = vq->vhost_hlen;
>> - zcopy = vhost_sock_zcopy(sock);
>>
>> for (;;) {
>> /* Release DMAs done buffers first */
> --
> To unsubscribe from this list: send the line "unsubscribe netdev" 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
* [PATCH] net: filter: Just In Time compiler for sparc
From: David Miller @ 2012-04-17 2:58 UTC (permalink / raw)
To: netdev; +Cc: sparclinux
Signed-off-by: David S. Miller <davem@davemloft.net>
---
I think I'll commit this to net-next so it's easier to track
any BPF changes we make there.
arch/sparc/Kconfig | 1 +
arch/sparc/Makefile | 1 +
arch/sparc/net/Makefile | 4 +
arch/sparc/net/bpf_jit.h | 52 +++
arch/sparc/net/bpf_jit_asm.S | 199 +++++++++++
arch/sparc/net/bpf_jit_comp.c | 785 +++++++++++++++++++++++++++++++++++++++++
6 files changed, 1042 insertions(+)
create mode 100644 arch/sparc/net/Makefile
create mode 100644 arch/sparc/net/bpf_jit.h
create mode 100644 arch/sparc/net/bpf_jit_asm.S
create mode 100644 arch/sparc/net/bpf_jit_comp.c
diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig
index db4e821..9f9afd9 100644
--- a/arch/sparc/Kconfig
+++ b/arch/sparc/Kconfig
@@ -30,6 +30,7 @@ config SPARC
select USE_GENERIC_SMP_HELPERS if SMP
select GENERIC_PCI_IOMAP
select HAVE_NMI_WATCHDOG if SPARC64
+ select HAVE_BPF_JIT
config SPARC32
def_bool !64BIT
diff --git a/arch/sparc/Makefile b/arch/sparc/Makefile
index eddcfb3..0e5de13 100644
--- a/arch/sparc/Makefile
+++ b/arch/sparc/Makefile
@@ -66,6 +66,7 @@ head-y += arch/sparc/kernel/init_task.o
core-y += arch/sparc/kernel/
core-y += arch/sparc/mm/ arch/sparc/math-emu/
+core-y += arch/sparc/net/
libs-y += arch/sparc/prom/
libs-y += arch/sparc/lib/
diff --git a/arch/sparc/net/Makefile b/arch/sparc/net/Makefile
new file mode 100644
index 0000000..1306a58
--- /dev/null
+++ b/arch/sparc/net/Makefile
@@ -0,0 +1,4 @@
+#
+# Arch-specific network modules
+#
+obj-$(CONFIG_BPF_JIT) += bpf_jit_asm.o bpf_jit_comp.o
diff --git a/arch/sparc/net/bpf_jit.h b/arch/sparc/net/bpf_jit.h
new file mode 100644
index 0000000..74f048b
--- /dev/null
+++ b/arch/sparc/net/bpf_jit.h
@@ -0,0 +1,52 @@
+#ifndef _BPF_JIT_H
+#define _BPF_JIT_H
+
+/* Conventions:
+ * %g1 : temporary
+ * %g2 : Secondary temporary used by SKB data helper stubs.
+ * %o0 : pointer to skb (first argument given to JIT function)
+ * %o1 : BPF A accumulator
+ * %o2 : BPF X accumulator
+ * %o3 : Holds saved %o7 so we can call helper functions without needing
+ * to allocate a register window.
+ * %o4 : skb->data
+ * %o5 : skb->len - skb->data_len
+ */
+
+#ifndef __ASSEMBLER__
+#define G0 0x00
+#define G1 0x01
+#define G3 0x03
+#define G6 0x06
+#define O0 0x08
+#define O1 0x09
+#define O2 0x0a
+#define O3 0x0b
+#define O4 0x0c
+#define O5 0x0d
+#define SP 0x0e
+#define O7 0x0f
+#define FP 0x1e
+
+#define r_SKB O0
+#define r_A O1
+#define r_X O2
+#define r_saved_O7 O3
+#define r_HEADLEN O4
+#define r_SKB_DATA O5
+#define r_TMP G1
+#define r_TMP2 G2
+#define r_OFF G3
+#else
+#define r_SKB %o0
+#define r_A %o1
+#define r_X %o2
+#define r_saved_O7 %o3
+#define r_HEADLEN %o4
+#define r_SKB_DATA %o5
+#define r_TMP %g1
+#define r_TMP2 %g2
+#define r_OFF %g3
+#endif
+
+#endif /* _BPF_JIT_H */
diff --git a/arch/sparc/net/bpf_jit_asm.S b/arch/sparc/net/bpf_jit_asm.S
new file mode 100644
index 0000000..fdc6932
--- /dev/null
+++ b/arch/sparc/net/bpf_jit_asm.S
@@ -0,0 +1,199 @@
+#include <asm/ptrace.h>
+
+#include "bpf_jit.h"
+
+#ifdef CONFIG_SPARC64
+#define SAVE_SZ 176
+#define SCRATCH_OFF STACK_BIAS + 128
+#define BE_PTR(label) be,pn %xcc, label
+#else
+#define SAVE_SZ 96
+#define SCRATCH_OFF 72
+#define BE_PTR(label) be label
+#endif
+
+#define SKF_MAX_NEG_OFF (-0x200000) /* SKF_LL_OFF from filter.h */
+
+ .text
+ .globl bpf_jit_load_word
+bpf_jit_load_word:
+ cmp r_OFF, 0
+ bl bpf_slow_path_word_neg
+ nop
+ .globl bpf_jit_load_word_positive_offset
+bpf_jit_load_word_positive_offset:
+ sub r_HEADLEN, r_OFF, r_TMP
+ cmp r_TMP, 3
+ ble bpf_slow_path_word
+ add r_SKB_DATA, r_OFF, r_TMP
+ andcc r_TMP, 3, %g0
+ bne load_word_unaligned
+ nop
+ retl
+ ld [r_SKB_DATA + r_OFF], r_A
+load_word_unaligned:
+ ldub [r_TMP + 0x0], r_OFF
+ ldub [r_TMP + 0x1], r_TMP2
+ sll r_OFF, 8, r_OFF
+ or r_OFF, r_TMP2, r_OFF
+ ldub [r_TMP + 0x2], r_TMP2
+ sll r_OFF, 8, r_OFF
+ or r_OFF, r_TMP2, r_OFF
+ ldub [r_TMP + 0x3], r_TMP2
+ sll r_OFF, 8, r_OFF
+ retl
+ or r_OFF, r_TMP2, r_A
+
+ .globl bpf_jit_load_half
+bpf_jit_load_half:
+ cmp r_OFF, 0
+ bl bpf_slow_path_half_neg
+ nop
+ .globl bpf_jit_load_half_positive_offset
+bpf_jit_load_half_positive_offset:
+ sub r_HEADLEN, r_OFF, r_TMP
+ cmp r_TMP, 1
+ ble bpf_slow_path_half
+ add r_SKB_DATA, r_OFF, r_TMP
+ andcc r_TMP, 1, %g0
+ bne load_half_unaligned
+ nop
+ retl
+ lduh [r_SKB_DATA + r_OFF], r_A
+load_half_unaligned:
+ ldub [r_TMP + 0x0], r_OFF
+ ldub [r_TMP + 0x1], r_TMP2
+ sll r_OFF, 8, r_OFF
+ retl
+ or r_OFF, r_TMP2, r_A
+
+ .globl bpf_jit_load_byte
+bpf_jit_load_byte:
+ cmp r_OFF, 0
+ bl bpf_slow_path_byte_neg
+ nop
+ .globl bpf_jit_load_byte_positive_offset
+bpf_jit_load_byte_positive_offset:
+ cmp r_OFF, r_HEADLEN
+ bge bpf_slow_path_byte
+ nop
+ retl
+ ldub [r_SKB_DATA + r_OFF], r_A
+
+ .globl bpf_jit_load_byte_msh
+bpf_jit_load_byte_msh:
+ cmp r_OFF, 0
+ bl bpf_slow_path_byte_msh_neg
+ nop
+ .globl bpf_jit_load_byte_msh_positive_offset
+bpf_jit_load_byte_msh_positive_offset:
+ cmp r_OFF, r_HEADLEN
+ bge bpf_slow_path_byte_msh
+ nop
+ ldub [r_SKB_DATA + r_OFF], r_OFF
+ and r_OFF, 0xf, r_OFF
+ retl
+ sll r_OFF, 2, r_X
+
+#define bpf_slow_path_common(LEN) \
+ save %sp, -SAVE_SZ, %sp; \
+ mov %i0, %o0; \
+ mov r_OFF, %o1; \
+ add %fp, SCRATCH_OFF, %o2; \
+ call skb_copy_bits; \
+ mov (LEN), %o3; \
+ cmp %o0, 0; \
+ restore;
+
+bpf_slow_path_word:
+ bpf_slow_path_common(4)
+ bl bpf_error
+ ld [%sp + SCRATCH_OFF], r_A
+ retl
+ nop
+bpf_slow_path_half:
+ bpf_slow_path_common(2)
+ bl bpf_error
+ lduh [%sp + SCRATCH_OFF], r_A
+ retl
+ nop
+bpf_slow_path_byte:
+ bpf_slow_path_common(1)
+ bl bpf_error
+ ldub [%sp + SCRATCH_OFF], r_A
+ retl
+ nop
+bpf_slow_path_byte_msh:
+ bpf_slow_path_common(1)
+ bl bpf_error
+ ldub [%sp + SCRATCH_OFF], r_A
+ and r_OFF, 0xf, r_OFF
+ retl
+ sll r_OFF, 2, r_X
+
+#define bpf_negative_common(LEN) \
+ save %sp, -SAVE_SZ, %sp; \
+ mov %i0, %o0; \
+ mov r_OFF, %o1; \
+ call bpf_internal_load_pointer_neg_helper; \
+ mov (LEN), %o2; \
+ mov %o0, r_TMP; \
+ cmp %o0, 0; \
+ BE_PTR(bpf_error); \
+ restore;
+
+bpf_slow_path_word_neg:
+ sethi %hi(SKF_MAX_NEG_OFF), r_TMP
+ cmp r_OFF, r_TMP
+ bl bpf_error
+ nop
+ .globl bpf_jit_load_word_negative_offset
+bpf_jit_load_word_negative_offset:
+ bpf_negative_common(4)
+ andcc r_TMP, 3, %g0
+ bne load_word_unaligned
+ nop
+ retl
+ ld [r_TMP], r_A
+
+bpf_slow_path_half_neg:
+ sethi %hi(SKF_MAX_NEG_OFF), r_TMP
+ cmp r_OFF, r_TMP
+ bl bpf_error
+ nop
+ .globl bpf_jit_load_half_negative_offset
+bpf_jit_load_half_negative_offset:
+ bpf_negative_common(2)
+ andcc r_TMP, 1, %g0
+ bne load_half_unaligned
+ nop
+ retl
+ lduh [r_TMP], r_A
+
+bpf_slow_path_byte_neg:
+ sethi %hi(SKF_MAX_NEG_OFF), r_TMP
+ cmp r_OFF, r_TMP
+ bl bpf_error
+ nop
+ .globl bpf_jit_load_byte_negative_offset
+bpf_jit_load_byte_negative_offset:
+ bpf_negative_common(1)
+ retl
+ ldub [r_TMP], r_A
+
+bpf_slow_path_byte_msh_neg:
+ sethi %hi(SKF_MAX_NEG_OFF), r_TMP
+ cmp r_OFF, r_TMP
+ bl bpf_error
+ nop
+ .globl bpf_jit_load_byte_msh_negative_offset
+bpf_jit_load_byte_msh_negative_offset:
+ bpf_negative_common(1)
+ ldub [r_TMP], r_OFF
+ and r_OFF, 0xf, r_OFF
+ retl
+ sll r_OFF, 2, r_X
+
+bpf_error:
+ jmpl r_saved_O7 + 8, %g0
+ clr %o0
diff --git a/arch/sparc/net/bpf_jit_comp.c b/arch/sparc/net/bpf_jit_comp.c
new file mode 100644
index 0000000..86349ca
--- /dev/null
+++ b/arch/sparc/net/bpf_jit_comp.c
@@ -0,0 +1,785 @@
+#include <linux/moduleloader.h>
+#include <linux/workqueue.h>
+#include <linux/netdevice.h>
+#include <linux/filter.h>
+#include <linux/cache.h>
+
+#include <asm/cacheflush.h>
+#include <asm/ptrace.h>
+
+#include "bpf_jit.h"
+
+int bpf_jit_enable __read_mostly;
+
+/* assembly code in arch/sparc/net/bpf_jit_asm.S */
+extern u32 bpf_jit_load_word[];
+extern u32 bpf_jit_load_half[];
+extern u32 bpf_jit_load_byte[];
+extern u32 bpf_jit_load_byte_msh[];
+extern u32 bpf_jit_load_word_positive_offset[];
+extern u32 bpf_jit_load_half_positive_offset[];
+extern u32 bpf_jit_load_byte_positive_offset[];
+extern u32 bpf_jit_load_byte_msh_positive_offset[];
+extern u32 bpf_jit_load_word_negative_offset[];
+extern u32 bpf_jit_load_half_negative_offset[];
+extern u32 bpf_jit_load_byte_negative_offset[];
+extern u32 bpf_jit_load_byte_msh_negative_offset[];
+
+static inline bool is_simm13(unsigned int value)
+{
+ return value + 0x1000 < 0x2000;
+}
+
+static void bpf_flush_icache(void *start_, void *end_)
+{
+#ifdef CONFIG_SPARC64
+ /* Cheetah's I-cache is fully coherent. */
+ if (tlb_type == spitfire) {
+ unsigned long start = (unsigned long) start_;
+ unsigned long end = (unsigned long) end_;
+
+ start &= ~7UL;
+ end = (end + 7UL) & ~7UL;
+ while (start < end) {
+ flushi(start);
+ start += 32;
+ }
+ }
+#endif
+}
+
+#define SEEN_DATAREF 1 /* might call external helpers */
+#define SEEN_XREG 2 /* ebx is used */
+#define SEEN_MEM 4 /* use mem[] for temporary storage */
+
+#define S13(X) ((X) & 0x1fff)
+#define IMMED 0x00002000
+#define RD(X) ((X) << 25)
+#define RS1(X) ((X) << 14)
+#define RS2(X) ((X))
+#define OP(X) ((X) << 30)
+#define OP2(X) ((X) << 22)
+#define OP3(X) ((X) << 19)
+#define COND(X) ((X) << 25)
+#define F1(X) OP(X)
+#define F2(X, Y) (OP(X) | OP2(Y))
+#define F3(X, Y) (OP(X) | OP3(Y))
+
+#define CONDN COND (0x0)
+#define CONDE COND (0x1)
+#define CONDLE COND (0x2)
+#define CONDL COND (0x3)
+#define CONDLEU COND (0x4)
+#define CONDCS COND (0x5)
+#define CONDNEG COND (0x6)
+#define CONDVC COND (0x7)
+#define CONDA COND (0x8)
+#define CONDNE COND (0x9)
+#define CONDG COND (0xa)
+#define CONDGE COND (0xb)
+#define CONDGU COND (0xc)
+#define CONDCC COND (0xd)
+#define CONDPOS COND (0xe)
+#define CONDVS COND (0xf)
+
+#define CONDGEU CONDCC
+#define CONDLU CONDCS
+
+#define WDISP22(X) (((X) >> 2) & 0x3fffff)
+
+#define BA (F2(0, 2) | CONDA)
+#define BGU (F2(0, 2) | CONDGU)
+#define BLEU (F2(0, 2) | CONDLEU)
+#define BGEU (F2(0, 2) | CONDGEU)
+#define BLU (F2(0, 2) | CONDLU)
+#define BE (F2(0, 2) | CONDE)
+#define BNE (F2(0, 2) | CONDNE)
+
+#ifdef CONFIG_SPARC64
+#define BNE_PTR (F2(0, 1) | CONDNE | (2 << 20))
+#else
+#define BNE_PTR BNE
+#endif
+
+#define SETHI(K, REG) \
+ (F2(0, 0x4) | RD(REG) | (((K) >> 10) & 0x3fffff))
+#define OR_LO(K, REG) \
+ (F3(2, 0x02) | IMMED | RS1(REG) | ((K) & 0x3ff) | RD(REG))
+
+#define ADD F3(2, 0x00)
+#define AND F3(2, 0x01)
+#define ANDCC F3(2, 0x11)
+#define OR F3(2, 0x02)
+#define SUB F3(2, 0x04)
+#define SUBCC F3(2, 0x14)
+#define MUL F3(2, 0x0a) /* umul */
+#define DIV F3(2, 0x0e) /* udiv */
+#define SLL F3(2, 0x25)
+#define SRL F3(2, 0x26)
+#define JMPL F3(2, 0x38)
+#define CALL F1(1)
+#define BR F2(0, 0x01)
+#define RD_Y F3(2, 0x28)
+#define WR_Y F3(2, 0x30)
+
+#define LD32 F3(3, 0x00)
+#define LD8 F3(3, 0x01)
+#define LD16 F3(3, 0x02)
+#define LD64 F3(3, 0x0b)
+#define ST32 F3(3, 0x04)
+
+#ifdef CONFIG_SPARC64
+#define LDPTR LD64
+#define BASE_STACKFRAME 176
+#else
+#define LDPTR LD32
+#define BASE_STACKFRAME 96
+#endif
+
+#define LD32I (LD32 | IMMED)
+#define LD8I (LD8 | IMMED)
+#define LD16I (LD16 | IMMED)
+#define LD64I (LD64 | IMMED)
+#define LDPTRI (LDPTR | IMMED)
+#define ST32I (ST32 | IMMED)
+
+#define emit_nop() \
+do { \
+ *prog++ = SETHI(0, G0); \
+} while (0)
+
+#define emit_neg() \
+do { /* sub %g0, r_A, r_A */ \
+ *prog++ = SUB | RS1(G0) | RS2(r_A) | RD(r_A); \
+} while (0)
+
+#define emit_reg_move(FROM, TO) \
+do { /* or %g0, FROM, TO */ \
+ *prog++ = OR | RS1(G0) | RS2(FROM) | RD(TO); \
+} while (0)
+
+#define emit_clear(REG) \
+do { /* or %g0, %g0, REG */ \
+ *prog++ = OR | RS1(G0) | RS2(G0) | RD(REG); \
+} while (0)
+
+#define emit_set_const(K, REG) \
+do { /* sethi %hi(K), REG */ \
+ *prog++ = SETHI(K, REG); \
+ /* or REG, %lo(K), REG */ \
+ *prog++ = OR_LO(K, REG); \
+} while (0)
+
+ /* Emit
+ *
+ * OP r_A, r_X, r_A
+ */
+#define emit_alu_X(OPCODE) \
+do { \
+ seen |= SEEN_XREG; \
+ *prog++ = OPCODE | RS1(r_A) | RS2(r_X) | RD(r_A); \
+} while (0)
+
+ /* Emit either:
+ *
+ * OP r_A, K, r_A
+ *
+ * or
+ *
+ * sethi %hi(K), r_TMP
+ * or r_TMP, %lo(K), r_TMP
+ * OP r_A, r_TMP, r_A
+ *
+ * depending upon whether K fits in a signed 13-bit
+ * immediate instruction field. Emit nothing if K
+ * is zero.
+ */
+#define emit_alu_K(OPCODE, K) \
+do { \
+ if (K) { \
+ unsigned int _insn = OPCODE; \
+ _insn |= RS1(r_A) | RD(r_A); \
+ if (is_simm13(K)) { \
+ *prog++ = _insn | IMMED | S13(K); \
+ } else { \
+ emit_set_const(K, r_TMP); \
+ *prog++ = _insn | RS2(r_TMP); \
+ } \
+ } \
+} while (0)
+
+#define emit_loadimm(K, DEST) \
+do { \
+ if (is_simm13(K)) { \
+ /* or %g0, K, DEST */ \
+ *prog++ = OR | IMMED | RS1(G0) | S13(K) | RD(DEST); \
+ } else { \
+ emit_set_const(K, DEST); \
+ } \
+} while (0)
+
+#define emit_loadptr(BASE, STRUCT, FIELD, DEST) \
+do { unsigned int _off = offsetof(STRUCT, FIELD); \
+ BUILD_BUG_ON(FIELD_SIZEOF(STRUCT, FIELD) != sizeof(void *)); \
+ *prog++ = LDPTRI | RS1(BASE) | S13(_off) | RD(DEST); \
+} while(0)
+
+#define emit_load32(BASE, STRUCT, FIELD, DEST) \
+do { unsigned int _off = offsetof(STRUCT, FIELD); \
+ BUILD_BUG_ON(FIELD_SIZEOF(STRUCT, FIELD) != sizeof(u32)); \
+ *prog++ = LD32I | RS1(BASE) | S13(_off) | RD(DEST); \
+} while(0)
+
+#define emit_load16(BASE, STRUCT, FIELD, DEST) \
+do { unsigned int _off = offsetof(STRUCT, FIELD); \
+ BUILD_BUG_ON(FIELD_SIZEOF(STRUCT, FIELD) != sizeof(u16)); \
+ *prog++ = LD16I | RS1(BASE) | S13(_off) | RD(DEST); \
+} while(0)
+
+#define __emit_load8(BASE, STRUCT, FIELD, DEST) \
+do { unsigned int _off = offsetof(STRUCT, FIELD); \
+ *prog++ = LD8I | RS1(BASE) | S13(_off) | RD(DEST); \
+} while(0)
+
+#define emit_load8(BASE, STRUCT, FIELD, DEST) \
+do { BUILD_BUG_ON(FIELD_SIZEOF(STRUCT, FIELD) != sizeof(u8)); \
+ __emit_load8(BASE, STRUCT, FIELD, DEST); \
+} while(0)
+
+#define emit_ldmem(OFF, DEST) \
+do { *prog++ = LD32I | RS1(FP) | S13(-(OFF)) | RD(DEST); \
+} while(0)
+
+#define emit_stmem(OFF, SRC) \
+do { *prog++ = LD32I | RS1(FP) | S13(-(OFF)) | RD(SRC); \
+} while(0)
+
+#define cpu_off offsetof(struct thread_info, cpu)
+
+#ifdef CONFIG_SMP
+#ifdef CONFIG_SPARC64
+#define emit_load_cpu(REG) \
+ emit_load16(G6, struct thread_info, cpu, REG)
+#else
+#define emit_load_cpu(REG) \
+ emit_load32(G6, struct thread_info, cpu, REG)
+#endif
+#else
+#define emit_load_cpu(REG) emit_clear(REG)
+#endif
+
+#define emit_skb_loadptr(FIELD, DEST) \
+ emit_loadptr(r_SKB, struct sk_buff, FIELD, DEST)
+#define emit_skb_load32(FIELD, DEST) \
+ emit_load32(r_SKB, struct sk_buff, FIELD, DEST)
+#define emit_skb_load16(FIELD, DEST) \
+ emit_load16(r_SKB, struct sk_buff, FIELD, DEST)
+#define __emit_skb_load8(FIELD, DEST) \
+ __emit_load8(r_SKB, struct sk_buff, FIELD, DEST)
+#define emit_skb_load8(FIELD, DEST) \
+ emit_load8(r_SKB, struct sk_buff, FIELD, DEST)
+
+#define emit_jmpl(BASE, IMM_OFF, LREG) \
+ *prog++ = (JMPL | IMMED | RS1(BASE) | S13(IMM_OFF) | RD(LREG))
+
+#define emit_call(FUNC) \
+do { void *_here = image + addrs[i] - 8; \
+ unsigned int _off = (void *)(FUNC) - _here; \
+ *prog++ = CALL | (((_off) >> 2) & 0x3fffffff); \
+ emit_nop(); \
+} while (0)
+
+#define emit_branch(BR_OPC, DEST) \
+do { unsigned int _here = addrs[i] - 8; \
+ *prog++ = BR_OPC | WDISP22((DEST) - _here); \
+} while(0)
+
+#define emit_branch_off(BR_OPC, OFF) \
+do { *prog++ = BR_OPC | WDISP22(OFF); \
+} while(0)
+
+#define emit_jump(DEST) emit_branch(BA, DEST)
+
+#define emit_read_y(REG) *prog++ = RD_Y | RD(REG);
+#define emit_write_y(REG) *prog++ = WR_Y | IMMED | RS1(REG) | S13(0);
+
+#define emit_cmp(R1, R2) \
+ *prog++ = (SUBCC | RS1(R1) | RS2(R2) | RD(G0))
+
+#define emit_cmpi(R1, IMM) \
+ *prog++ = (SUBCC | IMMED | RS1(R1) | S13(IMM) | RD(G0));
+
+#define emit_btst(R1, R2) \
+ *prog++ = (ANDCC | RS1(R1) | RS2(R2) | RD(G0))
+
+#define emit_btsti(R1, IMM) \
+ *prog++ = (ANDCC | IMMED | RS1(R1) | S13(IMM) | RD(G0));
+
+#define emit_sub(R1, R2, R3) \
+ *prog++ = (SUB | RS1(R1) | RS2(R2) | RD(R3))
+
+#define emit_subi(R1, IMM, R3) \
+ *prog++ = (SUB | IMMED | RS1(R1) | S13(IMM) | RD(R3))
+
+#define emit_add(R1, R2, R3) \
+ *prog++ = (ADD | RS1(R1) | RS2(R2) | RD(R3))
+
+#define emit_addi(R1, IMM, R3) \
+ *prog++ = (ADD | IMMED | RS1(R1) | S13(IMM) | RD(R3))
+
+#define emit_alloc_stack(SZ) \
+ *prog++ = (SUB | IMMED | RS1(SP) | S13(SZ) | RD(SP))
+
+#define emit_release_stack(SZ) \
+ *prog++ = (ADD | IMMED | RS1(SP) | S13(SZ) | RD(SP))
+
+void bpf_jit_compile(struct sk_filter *fp)
+{
+ unsigned int cleanup_addr, proglen, oldproglen = 0;
+ u32 temp[8], *prog, *func, seen = 0, pass;
+ const struct sock_filter *filter = fp->insns;
+ int i, flen = fp->len, pc_ret0 = -1;
+ unsigned int *addrs;
+ void *image;
+
+ if (!bpf_jit_enable)
+ return;
+
+ addrs = kmalloc(flen * sizeof(*addrs), GFP_KERNEL);
+ if (addrs == NULL)
+ return;
+
+ /* Before first pass, make a rough estimation of addrs[]
+ * each bpf instruction is translated to less than 64 bytes
+ */
+ for (proglen = 0, i = 0; i < flen; i++) {
+ proglen += 64;
+ addrs[i] = proglen;
+ }
+ cleanup_addr = proglen; /* epilogue address */
+ image = NULL;
+ for (pass = 0; pass < 10; pass++) {
+ u8 seen_or_pass0 = (pass == 0) ? (SEEN_XREG | SEEN_DATAREF | SEEN_MEM) : seen;
+
+ /* no prologue/epilogue for trivial filters (RET something) */
+ proglen = 0;
+ prog = temp;
+
+ /* Prologue */
+ if (seen_or_pass0) {
+ if (seen_or_pass0 & SEEN_MEM) {
+ unsigned int sz = BASE_STACKFRAME;
+ sz += BPF_MEMWORDS * sizeof(u32);
+ emit_alloc_stack(sz);
+ }
+
+ /* Make sure we dont leek kernel memory. */
+ if (seen_or_pass0 & SEEN_XREG)
+ emit_clear(r_X);
+
+ /* If this filter needs to access skb data,
+ * load %o4 and %o4 with:
+ * %o4 = skb->len - skb->data_len
+ * %o5 = skb->data
+ * And also back up %o7 into r_saved_O7 so we can
+ * invoke the stubs using 'call'.
+ */
+ if (seen_or_pass0 & SEEN_DATAREF) {
+ emit_load32(r_SKB, struct sk_buff, len, r_HEADLEN);
+ emit_load32(r_SKB, struct sk_buff, data_len, r_TMP);
+ emit_sub(r_HEADLEN, r_TMP, r_HEADLEN);
+ emit_loadptr(r_SKB, struct sk_buff, data, r_SKB_DATA);
+ }
+ }
+ emit_reg_move(O7, r_saved_O7);
+
+ switch (filter[0].code) {
+ case BPF_S_RET_K:
+ case BPF_S_LD_W_LEN:
+ case BPF_S_ANC_PROTOCOL:
+ case BPF_S_ANC_PKTTYPE:
+ case BPF_S_ANC_IFINDEX:
+ case BPF_S_ANC_MARK:
+ case BPF_S_ANC_RXHASH:
+ case BPF_S_ANC_CPU:
+ case BPF_S_ANC_QUEUE:
+ case BPF_S_LD_W_ABS:
+ case BPF_S_LD_H_ABS:
+ case BPF_S_LD_B_ABS:
+ /* The first instruction sets the A register (or is
+ * a "RET 'constant'")
+ */
+ break;
+ default:
+ /* Make sure we dont leak kernel information to the
+ * user.
+ */
+ emit_clear(r_A); /* A = 0 */
+ }
+
+ for (i = 0; i < flen; i++) {
+ unsigned int K = filter[i].k;
+ unsigned int t_offset;
+ unsigned int f_offset;
+ u32 t_op, f_op;
+ int ilen;
+
+ switch (filter[i].code) {
+ case BPF_S_ALU_ADD_X: /* A += X; */
+ emit_alu_X(ADD);
+ break;
+ case BPF_S_ALU_ADD_K: /* A += K; */
+ emit_alu_K(ADD, K);
+ break;
+ case BPF_S_ALU_SUB_X: /* A -= X; */
+ emit_alu_X(SUB);
+ break;
+ case BPF_S_ALU_SUB_K: /* A -= K */
+ emit_alu_K(SUB, K);
+ break;
+ case BPF_S_ALU_AND_X: /* A &= X */
+ emit_alu_X(AND);
+ break;
+ case BPF_S_ALU_AND_K: /* A &= K */
+ emit_alu_K(AND, K);
+ break;
+ case BPF_S_ALU_OR_X: /* A |= X */
+ emit_alu_X(OR);
+ break;
+ case BPF_S_ALU_OR_K: /* A |= K */
+ emit_alu_K(OR, K);
+ break;
+ case BPF_S_ALU_LSH_X: /* A <<= X */
+ emit_alu_X(SLL);
+ break;
+ case BPF_S_ALU_LSH_K: /* A <<= K */
+ emit_alu_K(SLL, K);
+ break;
+ case BPF_S_ALU_RSH_X: /* A >>= X */
+ emit_alu_X(SRL);
+ break;
+ case BPF_S_ALU_RSH_K: /* A >>= K */
+ emit_alu_K(SRL, K);
+ break;
+ case BPF_S_ALU_MUL_X: /* A *= X; */
+ emit_alu_X(MUL);
+ break;
+ case BPF_S_ALU_MUL_K: /* A *= K */
+ emit_alu_K(MUL, K);
+ break;
+ case BPF_S_ALU_DIV_K: /* A /= K */
+ emit_alu_K(MUL, K);
+ emit_read_y(r_A);
+ break;
+ case BPF_S_ALU_DIV_X: /* A /= X; */
+ emit_cmpi(r_X, 0);
+ if (pc_ret0 > 0) {
+ t_offset = addrs[pc_ret0 - 1];
+#ifdef CONFIG_SPARC32
+ emit_branch(BE, t_offset + 20);
+#else
+ emit_branch(BE, t_offset + 8);
+#endif
+ emit_nop(); /* delay slot */
+ } else {
+ emit_branch_off(BNE, 16);
+ emit_nop();
+#ifdef CONFIG_SPARC32
+ emit_jump(cleanup_addr + 20);
+#else
+ emit_jump(cleanup_addr + 8);
+#endif
+ emit_clear(r_A);
+ }
+ emit_write_y(G0);
+#ifdef CONFIG_SPARC32
+ emit_nop();
+ emit_nop();
+ emit_nop();
+#endif
+ emit_alu_X(DIV);
+ break;
+ case BPF_S_ALU_NEG:
+ emit_neg();
+ break;
+ case BPF_S_RET_K:
+ if (!K) {
+ if (pc_ret0 == -1)
+ pc_ret0 = i;
+ emit_clear(r_A);
+ } else {
+ emit_loadimm(K, r_A);
+ }
+ /* Fallthrough */
+ case BPF_S_RET_A:
+ if (seen_or_pass0) {
+ if (i != flen - 1) {
+ emit_jump(cleanup_addr);
+ emit_nop();
+ break;
+ }
+ if (seen_or_pass0 & SEEN_MEM) {
+ unsigned int sz = BASE_STACKFRAME;
+ sz += BPF_MEMWORDS * sizeof(u32);
+ emit_release_stack(sz);
+ }
+ }
+ /* jmpl %r_saved_O7 + 8, %g0 */
+ emit_jmpl(r_saved_O7, 8, G0);
+ emit_reg_move(r_A, O0); /* delay slot */
+ break;
+ case BPF_S_MISC_TAX:
+ seen |= SEEN_XREG;
+ emit_reg_move(r_A, r_X);
+ break;
+ case BPF_S_MISC_TXA:
+ seen |= SEEN_XREG;
+ emit_reg_move(r_X, r_A);
+ break;
+ case BPF_S_ANC_CPU:
+ emit_load_cpu(r_A);
+ break;
+ case BPF_S_ANC_PROTOCOL:
+ emit_skb_load16(protocol, r_A);
+ break;
+#if 0
+ /* GCC won't let us take the address of
+ * a bit field even though we very much
+ * know what we are doing here.
+ */
+ case BPF_S_ANC_PKTTYPE:
+ __emit_skb_load8(pkt_type, r_A);
+ emit_alu_K(SRL, 5);
+ break;
+#endif
+ case BPF_S_ANC_IFINDEX:
+ emit_skb_loadptr(dev, r_A);
+ emit_cmpi(r_A, 0);
+ emit_branch(BNE_PTR, cleanup_addr + 4);
+ emit_nop();
+ emit_load32(r_A, struct net_device, ifindex, r_A);
+ break;
+ case BPF_S_ANC_MARK:
+ emit_skb_load32(mark, r_A);
+ break;
+ case BPF_S_ANC_QUEUE:
+ emit_skb_load16(queue_mapping, r_A);
+ break;
+ case BPF_S_ANC_HATYPE:
+ emit_skb_loadptr(dev, r_A);
+ emit_cmpi(r_A, 0);
+ emit_branch(BNE_PTR, cleanup_addr + 4);
+ emit_nop();
+ emit_load16(r_A, struct net_device, type, r_A);
+ break;
+ case BPF_S_ANC_RXHASH:
+ emit_skb_load32(rxhash, r_A);
+ break;
+
+ case BPF_S_LD_IMM:
+ emit_loadimm(K, r_A);
+ break;
+ case BPF_S_LDX_IMM:
+ emit_loadimm(K, r_X);
+ break;
+ case BPF_S_LD_MEM:
+ emit_ldmem(K * 4, r_A);
+ break;
+ case BPF_S_LDX_MEM:
+ emit_ldmem(K * 4, r_X);
+ break;
+ case BPF_S_ST:
+ emit_stmem(K * 4, r_A);
+ break;
+ case BPF_S_STX:
+ emit_stmem(K * 4, r_X);
+ break;
+
+#define CHOOSE_LOAD_FUNC(K, func) \
+ ((int)K < 0 ? ((int)K >= SKF_LL_OFF ? func##_negative_offset : func) : func##_positive_offset)
+
+ case BPF_S_LD_W_ABS:
+ func = CHOOSE_LOAD_FUNC(K, bpf_jit_load_word);
+common_load: seen |= SEEN_DATAREF;
+ emit_loadimm(K, r_OFF);
+ emit_call(func);
+ break;
+ case BPF_S_LD_H_ABS:
+ func = CHOOSE_LOAD_FUNC(K, bpf_jit_load_half);
+ goto common_load;
+ case BPF_S_LD_B_ABS:
+ func = CHOOSE_LOAD_FUNC(K, bpf_jit_load_byte);
+ goto common_load;
+ case BPF_S_LDX_B_MSH:
+ func = CHOOSE_LOAD_FUNC(K, bpf_jit_load_byte_msh);
+ goto common_load;
+ case BPF_S_LD_W_IND:
+ func = bpf_jit_load_word;
+common_load_ind: seen |= SEEN_DATAREF | SEEN_XREG;
+ if (K) {
+ if (is_simm13(K)) {
+ emit_addi(r_X, K, r_OFF);
+ } else {
+ emit_loadimm(K, r_TMP);
+ emit_add(r_X, r_TMP, r_OFF);
+ }
+ } else {
+ emit_reg_move(r_X, r_OFF);
+ }
+ emit_call(func);
+ break;
+ case BPF_S_LD_H_IND:
+ func = bpf_jit_load_half;
+ goto common_load_ind;
+ case BPF_S_LD_B_IND:
+ func = bpf_jit_load_byte;
+ goto common_load_ind;
+ case BPF_S_JMP_JA:
+ emit_jump(addrs[i + K]);
+ emit_nop();
+ break;
+
+#define COND_SEL(CODE, TOP, FOP) \
+ case CODE: \
+ t_op = TOP; \
+ f_op = FOP; \
+ goto cond_branch
+
+ COND_SEL(BPF_S_JMP_JGT_K, BGU, BLEU);
+ COND_SEL(BPF_S_JMP_JGE_K, BGEU, BLU);
+ COND_SEL(BPF_S_JMP_JEQ_K, BE, BNE);
+ COND_SEL(BPF_S_JMP_JSET_K, BNE, BE);
+ COND_SEL(BPF_S_JMP_JGT_X, BGU, BLEU);
+ COND_SEL(BPF_S_JMP_JGE_X, BGEU, BLU);
+ COND_SEL(BPF_S_JMP_JEQ_X, BE, BNE);
+ COND_SEL(BPF_S_JMP_JSET_X, BNE, BE);
+
+cond_branch: f_offset = addrs[i + filter[i].jf];
+ t_offset = addrs[i + filter[i].jt];
+
+ /* same targets, can avoid doing the test :) */
+ if (filter[i].jt == filter[i].jf) {
+ emit_jump(t_offset);
+ emit_nop();
+ break;
+ }
+
+ switch (filter[i].code) {
+ case BPF_S_JMP_JGT_X:
+ case BPF_S_JMP_JGE_X:
+ case BPF_S_JMP_JEQ_X:
+ seen |= SEEN_XREG;
+ emit_cmp(r_A, r_X);
+ break;
+ case BPF_S_JMP_JSET_X:
+ seen |= SEEN_XREG;
+ emit_btst(r_A, r_X);
+ break;
+ case BPF_S_JMP_JEQ_K:
+ case BPF_S_JMP_JGT_K:
+ case BPF_S_JMP_JGE_K:
+ if (is_simm13(K)) {
+ emit_cmpi(r_A, K);
+ } else {
+ emit_loadimm(K, r_TMP);
+ emit_cmp(r_A, r_TMP);
+ }
+ break;
+ case BPF_S_JMP_JSET_K:
+ if (is_simm13(K)) {
+ emit_btsti(r_A, K);
+ } else {
+ emit_loadimm(K, r_TMP);
+ emit_btst(r_A, r_TMP);
+ }
+ break;
+ }
+ if (filter[i].jt != 0) {
+ if (filter[i].jf)
+ t_offset += 8;
+ emit_branch(t_op, t_offset);
+ emit_nop(); /* delay slot */
+ if (filter[i].jf) {
+ emit_jump(f_offset);
+ emit_nop();
+ }
+ break;
+ }
+ emit_branch(f_op, f_offset);
+ emit_nop(); /* delay slot */
+ break;
+
+ default:
+ /* hmm, too complex filter, give up with jit compiler */
+ goto out;
+ }
+ ilen = (void *) prog - (void *) temp;
+ if (image) {
+ if (unlikely(proglen + ilen > oldproglen)) {
+ pr_err("bpb_jit_compile fatal error\n");
+ kfree(addrs);
+ module_free(NULL, image);
+ return;
+ }
+ memcpy(image + proglen, temp, ilen);
+ }
+ proglen += ilen;
+ addrs[i] = proglen;
+ prog = temp;
+ }
+ /* last bpf instruction is always a RET :
+ * use it to give the cleanup instruction(s) addr
+ */
+ cleanup_addr = proglen - 8; /* jmpl; mov r_A,%o0; */
+ if (seen_or_pass0 & SEEN_MEM)
+ cleanup_addr -= 4; /* add %sp, X, %sp; */
+
+ if (image) {
+ if (proglen != oldproglen)
+ pr_err("bpb_jit_compile proglen=%u != oldproglen=%u\n",
+ proglen, oldproglen);
+ break;
+ }
+ if (proglen == oldproglen) {
+ image = module_alloc(max_t(unsigned int,
+ proglen,
+ sizeof(struct work_struct)));
+ if (!image)
+ goto out;
+ }
+ oldproglen = proglen;
+ }
+
+ if (bpf_jit_enable > 1)
+ pr_err("flen=%d proglen=%u pass=%d image=%p\n",
+ flen, proglen, pass, image);
+
+ if (image) {
+ if (bpf_jit_enable > 1)
+ print_hex_dump(KERN_ERR, "JIT code: ", DUMP_PREFIX_ADDRESS,
+ 16, 1, image, proglen, false);
+ bpf_flush_icache(image, image + proglen);
+ fp->bpf_func = (void *)image;
+ }
+out:
+ kfree(addrs);
+ return;
+}
+
+static void jit_free_defer(struct work_struct *arg)
+{
+ module_free(NULL, arg);
+}
+
+/* run from softirq, we must use a work_struct to call
+ * module_free() from process context
+ */
+void bpf_jit_free(struct sk_filter *fp)
+{
+ if (fp->bpf_func != sk_run_filter) {
+ struct work_struct *work = (struct work_struct *)fp->bpf_func;
+
+ INIT_WORK(work, jit_free_defer);
+ schedule_work(work);
+ }
+}
--
1.7.9.5
^ permalink raw reply related
* [PATCH 12/12] netfilter: export necessary function for generic proto
From: Gao feng @ 2012-04-17 2:56 UTC (permalink / raw)
To: pablo; +Cc: netfilter-devel, netdev, ebiederm, serge.hallyn, dlezcano,
Gao feng
In-Reply-To: <1334631383-12326-1-git-send-email-gaofeng@cn.fujitsu.com>
export two functions nf_conntrack_proto_generic_net_init and
nf_conntrack_proto_generic_net_fini.
Signed-off-by: Gao feng <gaofeng@cn.fujitsu.com>
---
include/net/netfilter/nf_conntrack_core.h | 3 +++
1 files changed, 3 insertions(+), 0 deletions(-)
diff --git a/include/net/netfilter/nf_conntrack_core.h b/include/net/netfilter/nf_conntrack_core.h
index aced085..3c3fabe 100644
--- a/include/net/netfilter/nf_conntrack_core.h
+++ b/include/net/netfilter/nf_conntrack_core.h
@@ -31,6 +31,9 @@ extern void nf_conntrack_cleanup(struct net *net);
extern int nf_conntrack_proto_init(void);
extern void nf_conntrack_proto_fini(void);
+extern int nf_conntrack_proto_generic_net_init(struct net *net);
+extern void nf_conntrack_proto_generic_net_fini(struct net *net);
+
extern bool
nf_ct_get_tuple(const struct sk_buff *skb,
unsigned int nhoff,
--
1.7.7.6
^ permalink raw reply related
* [PATCH 11/12] netfilter: udplite proto sysctl support for net
From: Gao feng @ 2012-04-17 2:56 UTC (permalink / raw)
To: pablo; +Cc: netfilter-devel, netdev, ebiederm, serge.hallyn, dlezcano,
Gao feng
In-Reply-To: <1334631383-12326-1-git-send-email-gaofeng@cn.fujitsu.com>
register pernet_operations nf_conntrack_net_proto_udplite_ops
when loading nf_conntrack_proto_udplite module,and unregister
it when removing.
It makes no senes to register subsys for udplite and udplite6,because
the nf_conntrack_l4proto_udplite4 and nf_conntrack_l4proto_udplite6 are
register or unregister together.
Signed-off-by: Gao feng <gaofeng@cn.fujitsu.com>
---
net/netfilter/nf_conntrack_proto_udplite.c | 83 +++++++++++++++++++++------
1 files changed, 64 insertions(+), 19 deletions(-)
diff --git a/net/netfilter/nf_conntrack_proto_udplite.c b/net/netfilter/nf_conntrack_proto_udplite.c
index e060639..61881bc 100644
--- a/net/netfilter/nf_conntrack_proto_udplite.c
+++ b/net/netfilter/nf_conntrack_proto_udplite.c
@@ -20,16 +20,11 @@
#include <linux/netfilter.h>
#include <linux/netfilter_ipv4.h>
#include <linux/netfilter_ipv6.h>
+#include <linux/netfilter/nf_conntrack_udplite.h>
#include <net/netfilter/nf_conntrack_l4proto.h>
#include <net/netfilter/nf_conntrack_ecache.h>
#include <net/netfilter/nf_log.h>
-enum udplite_conntrack {
- UDPLITE_CT_UNREPLIED,
- UDPLITE_CT_REPLIED,
- UDPLITE_CT_MAX
-};
-
static unsigned int udplite_timeouts[UDPLITE_CT_MAX] = {
[UDPLITE_CT_UNREPLIED] = 30*HZ,
[UDPLITE_CT_REPLIED] = 180*HZ,
@@ -70,7 +65,7 @@ static int udplite_print_tuple(struct seq_file *s,
static unsigned int *udplite_get_timeouts(struct net *net)
{
- return udplite_timeouts;
+ return net->ct.proto.sysctl_udplite_timeouts;
}
/* Returns verdict for packet, and may modify conntracktype */
@@ -203,19 +198,19 @@ udplite_timeout_nla_policy[CTA_TIMEOUT_UDPLITE_MAX+1] = {
#endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */
#ifdef CONFIG_SYSCTL
-static unsigned int udplite_sysctl_table_users;
-static struct ctl_table_header *udplite_sysctl_header;
static struct ctl_table udplite_sysctl_table[] = {
{
.procname = "nf_conntrack_udplite_timeout",
- .data = &udplite_timeouts[UDPLITE_CT_UNREPLIED],
+ .data = &init_net.ct.proto.
+ sysctl_udplite_timeouts[UDPLITE_CT_UNREPLIED],
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = proc_dointvec_jiffies,
},
{
.procname = "nf_conntrack_udplite_timeout_stream",
- .data = &udplite_timeouts[UDPLITE_CT_REPLIED],
+ .data = &init_net.ct.proto.
+ sysctl_udplite_timeouts[UDPLITE_CT_REPLIED],
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = proc_dointvec_jiffies,
@@ -252,11 +247,6 @@ static struct nf_conntrack_l4proto nf_conntrack_l4proto_udplite4 __read_mostly =
.nla_policy = udplite_timeout_nla_policy,
},
#endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */
-#ifdef CONFIG_SYSCTL
- .ctl_table_users = &udplite_sysctl_table_users,
- .ctl_table_header = &udplite_sysctl_header,
- .ctl_table = udplite_sysctl_table,
-#endif
};
static struct nf_conntrack_l4proto nf_conntrack_l4proto_udplite6 __read_mostly =
@@ -287,11 +277,60 @@ static struct nf_conntrack_l4proto nf_conntrack_l4proto_udplite6 __read_mostly =
.nla_policy = udplite_timeout_nla_policy,
},
#endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */
+};
+
+static int nf_conntrack_proto_udplite_net_init(struct net *net)
+{
+ struct ctl_table *table;
+ int i, ret = 0;
+ for (i = 0; i < UDPLITE_CT_MAX; i++)
+ net->ct.proto.sysctl_udplite_timeouts[i] = udplite_timeouts[i];
+
+#ifdef CONFIG_SYSCTL
+ table = kmemdup(udplite_sysctl_table,
+ sizeof(udplite_sysctl_table),
+ GFP_KERNEL);
+ if (!table)
+ return -ENOMEM;
+
+ table[0].data = &net->ct.proto.
+ sysctl_udplite_timeouts[UDPLITE_CT_UNREPLIED];
+ table[1].data = &net->ct.proto.
+ sysctl_udplite_timeouts[UDPLITE_CT_REPLIED];
+
+ ret = nf_ct_register_net_sysctl(net,
+ &net->ct.proto.udplite_sysctl_header,
+ nf_net_netfilter_sysctl_path,
+ table,
+ NULL);
+ if (ret < 0) {
+ printk(KERN_ERR
+ "nf_conntrack_proto_udplite:"
+ " can't register to sysctl.\n");
+ goto out_register;
+ }
+ return 0;
+out_register:
+ kfree(table);
+#endif
+ return ret;
+}
+
+static void nf_conntrack_proto_udplite_net_fini(struct net *net)
+{
#ifdef CONFIG_SYSCTL
- .ctl_table_users = &udplite_sysctl_table_users,
- .ctl_table_header = &udplite_sysctl_header,
- .ctl_table = udplite_sysctl_table,
+ struct ctl_table *table;
+ table = net->ct.proto.udplite_sysctl_header->ctl_table_arg;
+
+ nf_ct_unregister_net_sysctl(&net->ct.proto.udplite_sysctl_header,
+ table,
+ NULL);
#endif
+}
+
+static struct pernet_operations nf_conntrack_net_proto_udplite_ops = {
+ .init = nf_conntrack_proto_udplite_net_init,
+ .exit = nf_conntrack_proto_udplite_net_fini,
};
static int __init nf_conntrack_proto_udplite_init(void)
@@ -304,7 +343,12 @@ static int __init nf_conntrack_proto_udplite_init(void)
err = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_udplite6);
if (err < 0)
goto err2;
+ err = register_pernet_subsys(&nf_conntrack_net_proto_udplite_ops);
+ if (err < 0)
+ goto err3;
return 0;
+err3:
+ nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_udplite6);
err2:
nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_udplite4);
err1:
@@ -313,6 +357,7 @@ err1:
static void __exit nf_conntrack_proto_udplite_exit(void)
{
+ unregister_pernet_subsys(&nf_conntrack_net_proto_udplite_ops);
nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_udplite6);
nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_udplite4);
}
--
1.7.7.6
^ permalink raw reply related
* [PATCH 10/12] netfilter: sctp proto sysctl support for net namespace
From: Gao feng @ 2012-04-17 2:56 UTC (permalink / raw)
To: pablo; +Cc: netfilter-devel, netdev, ebiederm, serge.hallyn, dlezcano,
Gao feng
In-Reply-To: <1334631383-12326-1-git-send-email-gaofeng@cn.fujitsu.com>
register pernet_operations nf_conntrack_net_proto_sctp_ops
when loading nf_conntrack_proto_sctp module,and unregister
it when removing.
It makes no senes to register subsys for sctp and sctp6,because
the nf_conntrack_l4proto_sctp4 and nf_conntrack_l4proto_sctp6 are
register or unregister together.
Signed-off-by: Gao feng <gaofeng@cn.fujitsu.com>
---
net/netfilter/nf_conntrack_proto_sctp.c | 205 ++++++++++++++++++++++++++-----
1 files changed, 175 insertions(+), 30 deletions(-)
diff --git a/net/netfilter/nf_conntrack_proto_sctp.c b/net/netfilter/nf_conntrack_proto_sctp.c
index 72b5088..866d151 100644
--- a/net/netfilter/nf_conntrack_proto_sctp.c
+++ b/net/netfilter/nf_conntrack_proto_sctp.c
@@ -281,7 +281,7 @@ static int sctp_new_state(enum ip_conntrack_dir dir,
static unsigned int *sctp_get_timeouts(struct net *net)
{
- return sctp_timeouts;
+ return net->ct.proto.sysctl_sctp_timeouts;
}
/* Returns verdict for packet, or -NF_ACCEPT for invalid. */
@@ -599,56 +599,60 @@ sctp_timeout_nla_policy[CTA_TIMEOUT_SCTP_MAX+1] = {
};
#endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */
-
#ifdef CONFIG_SYSCTL
-static unsigned int sctp_sysctl_table_users;
-static struct ctl_table_header *sctp_sysctl_header;
static struct ctl_table sctp_sysctl_table[] = {
{
.procname = "nf_conntrack_sctp_timeout_closed",
- .data = &sctp_timeouts[SCTP_CONNTRACK_CLOSED],
+ .data = &init_net.ct.proto.
+ sysctl_sctp_timeouts[SCTP_CONNTRACK_CLOSED],
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = proc_dointvec_jiffies,
},
{
.procname = "nf_conntrack_sctp_timeout_cookie_wait",
- .data = &sctp_timeouts[SCTP_CONNTRACK_COOKIE_WAIT],
+ .data = &init_net.ct.proto.
+ sysctl_sctp_timeouts[SCTP_CONNTRACK_COOKIE_WAIT],
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = proc_dointvec_jiffies,
},
{
.procname = "nf_conntrack_sctp_timeout_cookie_echoed",
- .data = &sctp_timeouts[SCTP_CONNTRACK_COOKIE_ECHOED],
+ .data = &init_net.ct.proto.
+ sysctl_sctp_timeouts[SCTP_CONNTRACK_COOKIE_ECHOED],
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = proc_dointvec_jiffies,
},
{
.procname = "nf_conntrack_sctp_timeout_established",
- .data = &sctp_timeouts[SCTP_CONNTRACK_ESTABLISHED],
+ .data = &init_net.ct.proto.
+ sysctl_sctp_timeouts[SCTP_CONNTRACK_ESTABLISHED],
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = proc_dointvec_jiffies,
},
{
.procname = "nf_conntrack_sctp_timeout_shutdown_sent",
- .data = &sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_SENT],
+ .data = &init_net.ct.proto.
+ sysctl_sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_SENT],
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = proc_dointvec_jiffies,
},
{
.procname = "nf_conntrack_sctp_timeout_shutdown_recd",
- .data = &sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_RECD],
+ .data = &init_net.ct.proto.
+ sysctl_sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_RECD],
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = proc_dointvec_jiffies,
},
{
.procname = "nf_conntrack_sctp_timeout_shutdown_ack_sent",
- .data = &sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_ACK_SENT],
+ .data = &init_net.ct.proto.
+ sysctl_sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_ACK_SENT],
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = proc_dointvec_jiffies,
@@ -660,49 +664,56 @@ static struct ctl_table sctp_sysctl_table[] = {
static struct ctl_table sctp_compat_sysctl_table[] = {
{
.procname = "ip_conntrack_sctp_timeout_closed",
- .data = &sctp_timeouts[SCTP_CONNTRACK_CLOSED],
+ .data = &init_net.ct.proto.
+ sysctl_sctp_timeouts[SCTP_CONNTRACK_CLOSED],
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = proc_dointvec_jiffies,
},
{
.procname = "ip_conntrack_sctp_timeout_cookie_wait",
- .data = &sctp_timeouts[SCTP_CONNTRACK_COOKIE_WAIT],
+ .data = &init_net.ct.proto.
+ sysctl_sctp_timeouts[SCTP_CONNTRACK_COOKIE_WAIT],
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = proc_dointvec_jiffies,
},
{
.procname = "ip_conntrack_sctp_timeout_cookie_echoed",
- .data = &sctp_timeouts[SCTP_CONNTRACK_COOKIE_ECHOED],
+ .data = &init_net.ct.proto.
+ sysctl_sctp_timeouts[SCTP_CONNTRACK_COOKIE_ECHOED],
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = proc_dointvec_jiffies,
},
{
.procname = "ip_conntrack_sctp_timeout_established",
- .data = &sctp_timeouts[SCTP_CONNTRACK_ESTABLISHED],
+ .data = &init_net.ct.proto.
+ sysctl_sctp_timeouts[SCTP_CONNTRACK_ESTABLISHED],
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = proc_dointvec_jiffies,
},
{
.procname = "ip_conntrack_sctp_timeout_shutdown_sent",
- .data = &sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_SENT],
+ .data = &init_net.ct.proto.
+ sysctl_sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_SENT],
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = proc_dointvec_jiffies,
},
{
.procname = "ip_conntrack_sctp_timeout_shutdown_recd",
- .data = &sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_RECD],
+ .data = &init_net.ct.proto.
+ sysctl_sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_RECD],
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = proc_dointvec_jiffies,
},
{
.procname = "ip_conntrack_sctp_timeout_shutdown_ack_sent",
- .data = &sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_ACK_SENT],
+ .data = &init_net.ct.proto.
+ sysctl_sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_ACK_SENT],
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = proc_dointvec_jiffies,
@@ -742,14 +753,6 @@ static struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp4 __read_mostly = {
.nla_policy = sctp_timeout_nla_policy,
},
#endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */
-#ifdef CONFIG_SYSCTL
- .ctl_table_users = &sctp_sysctl_table_users,
- .ctl_table_header = &sctp_sysctl_header,
- .ctl_table = sctp_sysctl_table,
-#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT
- .ctl_compat_table = sctp_compat_sysctl_table,
-#endif
-#endif
};
static struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp6 __read_mostly = {
@@ -782,11 +785,146 @@ static struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp6 __read_mostly = {
},
#endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */
#endif
+};
+
+static int nf_conntrack_proto_sctp_net_init(struct net *net)
+{
+ struct ctl_table *table;
+ int i, ret = 0;
+ for (i = 0; i < SCTP_CONNTRACK_MAX; i++)
+ net->ct.proto.sysctl_sctp_timeouts[i] = sctp_timeouts[i];
+
#ifdef CONFIG_SYSCTL
- .ctl_table_users = &sctp_sysctl_table_users,
- .ctl_table_header = &sctp_sysctl_header,
- .ctl_table = sctp_sysctl_table,
+ table = kmemdup(sctp_sysctl_table,
+ sizeof(sctp_sysctl_table),
+ GFP_KERNEL);
+ if (!table)
+ return -ENOMEM;
+ table[0].data = &net->ct.proto.
+ sysctl_sctp_timeouts[SCTP_CONNTRACK_CLOSED];
+ table[1].data = &net->ct.proto.
+ sysctl_sctp_timeouts[SCTP_CONNTRACK_COOKIE_WAIT];
+ table[2].data = &net->ct.proto.
+ sysctl_sctp_timeouts[SCTP_CONNTRACK_COOKIE_ECHOED];
+ table[3].data = &net->ct.proto.
+ sysctl_sctp_timeouts[SCTP_CONNTRACK_ESTABLISHED];
+ table[4].data = &net->ct.proto.
+ sysctl_sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_SENT];
+ table[5].data = &net->ct.proto.
+ sysctl_sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_RECD];
+ table[6].data = &net->ct.proto.
+ sysctl_sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_ACK_SENT];
+
+ ret = nf_ct_register_net_sysctl(net,
+ &net->ct.proto.sctp_sysctl_header,
+ nf_net_netfilter_sysctl_path,
+ table,
+ NULL);
+ if (ret < 0) {
+ printk(KERN_ERR
+ "nf_conntrack_proto_sctp:"
+ " can't register to sysctl.\n");
+ goto out_register;
+ }
+ return 0;
+out_register:
+ kfree(table);
#endif
+ return ret;
+}
+
+static void nf_conntrack_proto_sctp_net_fini(struct net *net)
+{
+#ifdef CONFIG_SYSCTL
+ struct ctl_table *table;
+ table = net->ct.proto.sctp_sysctl_header->ctl_table_arg;
+
+ nf_ct_unregister_net_sysctl(&net->ct.proto.sctp_sysctl_header,
+ table,
+ NULL);
+#endif
+}
+
+static int nf_conntrack_proto_sctp_compat_init(struct net *net)
+{
+ int ret = 0;
+#ifdef CONFIG_SYSCTL
+#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT
+ struct ctl_table *compat_table;
+ compat_table = kmemdup(sctp_compat_sysctl_table,
+ sizeof(sctp_compat_sysctl_table),
+ GFP_KERNEL);
+ if (!compat_table)
+ return -ENOMEM;
+
+ compat_table[0].data = &net->ct.proto.
+ sysctl_sctp_timeouts[SCTP_CONNTRACK_CLOSED];
+ compat_table[1].data = &net->ct.proto.
+ sysctl_sctp_timeouts[SCTP_CONNTRACK_COOKIE_WAIT];
+ compat_table[2].data = &net->ct.proto.
+ sysctl_sctp_timeouts[SCTP_CONNTRACK_COOKIE_ECHOED];
+ compat_table[3].data = &net->ct.proto.
+ sysctl_sctp_timeouts[SCTP_CONNTRACK_ESTABLISHED];
+ compat_table[4].data = &net->ct.proto.
+ sysctl_sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_SENT];
+ compat_table[5].data = &net->ct.proto.
+ sysctl_sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_RECD];
+ compat_table[6].data = &net->ct.proto.
+ sysctl_sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_ACK_SENT];
+
+ ret = nf_ct_register_net_sysctl(net,
+ &net->ct.proto.sctp_compat_header,
+ nf_net_ipv4_netfilter_sysctl_path,
+ compat_table,
+ NULL);
+ if (ret < 0) {
+ printk(KERN_ERR
+ "nf_conntrack_proto_sctp:"
+ " can't register to compat sysctl.\n");
+ goto out_register;
+ }
+ return 0;
+out_register:
+ kfree(compat_table);
+#endif
+#endif
+ return ret;
+}
+
+static void nf_conntrack_proto_sctp_compat_fini(struct net *net)
+{
+#ifdef CONFIG_SYSCTL
+#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT
+ struct ctl_table *compat_table;
+ compat_table = net->ct.proto.sctp_compat_header->ctl_table_arg;
+ nf_ct_unregister_net_sysctl(&net->ct.proto.sctp_compat_header,
+ compat_table,
+ NULL);
+#endif
+#endif
+}
+
+static int nf_conntrack_net_proto_sctp_init(struct net *net)
+{
+ int ret;
+ ret = nf_conntrack_proto_sctp_net_init(net);
+ if (ret < 0)
+ return ret;
+ ret = nf_conntrack_proto_sctp_compat_init(net);
+ if (ret < 0)
+ nf_conntrack_proto_sctp_net_fini(net);
+ return ret;
+}
+
+static void nf_conntrack_net_proto_sctp_fini(struct net *net)
+{
+ nf_conntrack_proto_sctp_compat_fini(net);
+ nf_conntrack_proto_sctp_net_fini(net);
+}
+
+static struct pernet_operations nf_conntrack_net_proto_sctp_ops = {
+ .init = nf_conntrack_net_proto_sctp_init,
+ .exit = nf_conntrack_net_proto_sctp_fini,
};
static int __init nf_conntrack_proto_sctp_init(void)
@@ -803,9 +941,15 @@ static int __init nf_conntrack_proto_sctp_init(void)
pr_err("nf_conntrack_l4proto_sctp6: protocol register failed\n");
goto cleanup_sctp4;
}
-
+ ret = register_pernet_subsys(&nf_conntrack_net_proto_sctp_ops);
+ if (ret) {
+ pr_err("nf_conntrack: sctp pernet subsys register failed\n");
+ goto cleanup_sctp6;
+ }
return ret;
+ cleanup_sctp6:
+ nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_sctp6);
cleanup_sctp4:
nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_sctp4);
out:
@@ -814,6 +958,7 @@ static int __init nf_conntrack_proto_sctp_init(void)
static void __exit nf_conntrack_proto_sctp_fini(void)
{
+ unregister_pernet_subsys(&nf_conntrack_net_proto_sctp_ops);
nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_sctp6);
nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_sctp4);
}
--
1.7.7.6
^ permalink raw reply related
* [PATCH 08/12] netfilter: ipv4 sysctl support for net namespace
From: Gao feng @ 2012-04-17 2:56 UTC (permalink / raw)
To: pablo; +Cc: netfilter-devel, netdev, ebiederm, serge.hallyn, dlezcano,
Gao feng
In-Reply-To: <1334631383-12326-1-git-send-email-gaofeng@cn.fujitsu.com>
delete the ctl_table_header, ctl_table_path, ctl_table
from struct nf_conntrack_l3proto,
delete the ctl_table_header, ctl_table, ctl_table_users,
ctl_compat_table_header, ctl_compat_table from struct
nf_conntract_l4proto.
we have removed these field to the struct netns_ct_proto.
register pernet_operations nf_conntrack_net_proto_ipv4_ops
when loading nf_conntrack_ipv4 module,and unregister it when
removing.
nf_conntrack_l4proto.h exports the init,fini functions of l4proto.
Signed-off-by: Gao feng <gaofeng@cn.fujitsu.com>
---
include/net/netfilter/nf_conntrack_l3proto.h | 6 --
include/net/netfilter/nf_conntrack_l4proto.h | 38 +++++++---
net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c | 96 ++++++++++++++++++++++-
3 files changed, 119 insertions(+), 21 deletions(-)
diff --git a/include/net/netfilter/nf_conntrack_l3proto.h b/include/net/netfilter/nf_conntrack_l3proto.h
index e8010f4..cf14b99 100644
--- a/include/net/netfilter/nf_conntrack_l3proto.h
+++ b/include/net/netfilter/nf_conntrack_l3proto.h
@@ -63,12 +63,6 @@ struct nf_conntrack_l3proto {
size_t nla_size;
-#ifdef CONFIG_SYSCTL
- struct ctl_table_header *ctl_table_header;
- struct ctl_path *ctl_table_path;
- struct ctl_table *ctl_table;
-#endif /* CONFIG_SYSCTL */
-
/* Module (if any) which this is connected to. */
struct module *me;
};
diff --git a/include/net/netfilter/nf_conntrack_l4proto.h b/include/net/netfilter/nf_conntrack_l4proto.h
index 3b572bb..167d9c2 100644
--- a/include/net/netfilter/nf_conntrack_l4proto.h
+++ b/include/net/netfilter/nf_conntrack_l4proto.h
@@ -93,16 +93,6 @@ struct nf_conntrack_l4proto {
const struct nla_policy *nla_policy;
} ctnl_timeout;
#endif
-
-#ifdef CONFIG_SYSCTL
- struct ctl_table_header **ctl_table_header;
- struct ctl_table *ctl_table;
- unsigned int *ctl_table_users;
-#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT
- struct ctl_table_header *ctl_compat_table_header;
- struct ctl_table *ctl_compat_table;
-#endif
-#endif
/* Protocol name */
const char *name;
@@ -134,6 +124,34 @@ extern int nf_ct_port_nlattr_to_tuple(struct nlattr *tb[],
extern int nf_ct_port_nlattr_tuple_size(void);
extern const struct nla_policy nf_ct_port_nla_policy[];
+extern int nf_ct_register_net_sysctl(struct net *net,
+ struct ctl_table_header **header,
+ struct ctl_path *path,
+ struct ctl_table *table,
+ unsigned int *users);
+
+extern void nf_ct_unregister_net_sysctl(struct ctl_table_header **header,
+ struct ctl_table *table,
+ unsigned int *users);
+
+extern int nf_conntrack_proto_ipv4_tcp_init(struct net *net);
+extern void nf_conntrack_proto_ipv4_tcp_fini(struct net *net);
+
+extern int nf_conntrack_proto_ipv6_tcp_init(struct net *net);
+extern void nf_conntrack_proto_ipv6_tcp_fini(struct net *net);
+
+extern int nf_conntrack_proto_ipv4_udp_init(struct net *net);
+extern void nf_conntrack_proto_ipv4_udp_fini(struct net *net);
+
+extern int nf_conntrack_proto_ipv6_udp_init(struct net *net);
+extern void nf_conntrack_proto_ipv6_udp_fini(struct net *net);
+
+extern int nf_conntrack_proto_ipv4_icmp_init(struct net *net);
+extern void nf_conntrack_proto_ipv4_icmp_fini(struct net *net);
+
+extern int nf_conntrack_proto_icmpv6_net_init(struct net *net);
+extern void nf_conntrack_proto_icmpv6_net_fini(struct net *net);
+
#ifdef CONFIG_SYSCTL
#ifdef DEBUG_INVALID_PACKETS
#define LOG_INVALID(net, proto) \
diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
index de9da21..234ff9a 100644
--- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
+++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
@@ -355,10 +355,6 @@ struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv4 __read_mostly = {
.nlattr_to_tuple = ipv4_nlattr_to_tuple,
.nla_policy = ipv4_nla_policy,
#endif
-#if defined(CONFIG_SYSCTL) && defined(CONFIG_NF_CONNTRACK_PROC_COMPAT)
- .ctl_table_path = nf_net_ipv4_netfilter_sysctl_path,
- .ctl_table = ip_ct_sysctl_table,
-#endif
.me = THIS_MODULE,
};
@@ -369,6 +365,86 @@ MODULE_ALIAS("nf_conntrack-" __stringify(AF_INET));
MODULE_ALIAS("ip_conntrack");
MODULE_LICENSE("GPL");
+static int nf_conntrack_proto_ipv4_net_init(struct net *net)
+{
+ int ret = 0;
+#ifdef CONFIG_SYSCTL
+#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT
+ struct ctl_table *table;
+ table = kmemdup(ip_ct_sysctl_table,
+ sizeof(ip_ct_sysctl_table),
+ GFP_KERNEL);
+ if (!table)
+ return -ENOMEM;
+ table[1].data = &net->ct.count;
+ table[2].data = &net->ct.htable_size;
+ table[3].data = &net->ct.sysctl_checksum;
+ table[4].data = &net->ct.sysctl_log_invalid;
+ net->ct.proto.ipv4_compat_header =
+ register_net_sysctl_table(net,
+ nf_net_ipv4_netfilter_sysctl_path,
+ table);
+ if (!net->ct.proto.ipv4_compat_header)
+ goto out_register;
+ return 0;
+out_register:
+ kfree(table);
+#endif
+#endif
+ return ret;
+}
+
+static void nf_conntrack_proto_ipv4_net_fini(struct net *net)
+{
+#ifdef CONFIG_SYSCTL
+#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT
+ struct ctl_table *table;
+ table = net->ct.proto.ipv4_compat_header->ctl_table_arg;
+ unregister_net_sysctl_table(net->ct.proto.ipv4_compat_header);
+ kfree(table);
+#endif
+#endif
+}
+
+static int nf_conntrack_net_proto_ipv4_init(struct net *net)
+{
+ int ret;
+
+ ret = nf_conntrack_proto_ipv4_net_init(net);
+ if (ret < 0)
+ return ret;
+ ret = nf_conntrack_proto_ipv4_tcp_init(net);
+ if (ret < 0)
+ goto cleanup_ipv4;
+ ret = nf_conntrack_proto_ipv4_udp_init(net);
+ if (ret < 0)
+ goto cleanup_tcp;
+ ret = nf_conntrack_proto_ipv4_icmp_init(net);
+ if (ret < 0)
+ goto cleanup_udp;
+ return 0;
+ cleanup_udp:
+ nf_conntrack_proto_ipv4_udp_fini(net);
+ cleanup_tcp:
+ nf_conntrack_proto_ipv4_tcp_fini(net);
+ cleanup_ipv4:
+ nf_conntrack_proto_ipv4_net_fini(net);
+ return ret;
+}
+
+static void nf_conntrack_net_proto_ipv4_fini(struct net *net)
+{
+ nf_conntrack_proto_ipv4_icmp_fini(net);
+ nf_conntrack_proto_ipv4_udp_fini(net);
+ nf_conntrack_proto_ipv4_tcp_fini(net);
+ nf_conntrack_proto_ipv4_net_fini(net);
+}
+
+static struct pernet_operations nf_conntrack_net_proto_ipv4_ops = {
+ .init = nf_conntrack_net_proto_ipv4_init,
+ .exit = nf_conntrack_net_proto_ipv4_fini,
+};
+
static int __init nf_conntrack_l3proto_ipv4_init(void)
{
int ret = 0;
@@ -417,11 +493,20 @@ static int __init nf_conntrack_l3proto_ipv4_init(void)
if (ret < 0)
goto cleanup_hooks;
#endif
+ ret = register_pernet_subsys(&nf_conntrack_net_proto_ipv4_ops);
+ if (ret < 0)
+ goto cleanup_compat;
+
return ret;
+
+ cleanup_compat:
#if defined(CONFIG_PROC_FS) && defined(CONFIG_NF_CONNTRACK_PROC_COMPAT)
+ nf_conntrack_ipv4_compat_fini();
+
cleanup_hooks:
- nf_unregister_hooks(ipv4_conntrack_ops, ARRAY_SIZE(ipv4_conntrack_ops));
#endif
+ nf_unregister_hooks(ipv4_conntrack_ops,
+ ARRAY_SIZE(ipv4_conntrack_ops));
cleanup_ipv4:
nf_conntrack_l3proto_unregister(&nf_conntrack_l3proto_ipv4);
cleanup_icmp:
@@ -438,6 +523,7 @@ static int __init nf_conntrack_l3proto_ipv4_init(void)
static void __exit nf_conntrack_l3proto_ipv4_fini(void)
{
synchronize_net();
+ unregister_pernet_subsys(&nf_conntrack_net_proto_ipv4_ops);
#if defined(CONFIG_PROC_FS) && defined(CONFIG_NF_CONNTRACK_PROC_COMPAT)
nf_conntrack_ipv4_compat_fini();
#endif
--
1.7.7.6
^ permalink raw reply related
* [PATCH 02/12] netfilter: don't register sysctl when register proto
From: Gao feng @ 2012-04-17 2:56 UTC (permalink / raw)
To: pablo; +Cc: netfilter-devel, netdev, ebiederm, serge.hallyn, dlezcano,
Gao feng
In-Reply-To: <1334631383-12326-1-git-send-email-gaofeng@cn.fujitsu.com>
delete nf_ct_l[3,4]proto_register_sysctl when register l[3,4]proto.
and add nf_ct_register_net_sysctl,nf_ct_unregister_net_sysctl to
register the sysctl for net namespace.
Signed-off-by: Gao feng <gaofeng@cn.fujitsu.com>
---
net/netfilter/nf_conntrack_proto.c | 109 +++++-------------------------------
1 files changed, 15 insertions(+), 94 deletions(-)
diff --git a/net/netfilter/nf_conntrack_proto.c b/net/netfilter/nf_conntrack_proto.c
index be3da2c..207cdd8 100644
--- a/net/netfilter/nf_conntrack_proto.c
+++ b/net/netfilter/nf_conntrack_proto.c
@@ -35,12 +35,15 @@ EXPORT_SYMBOL_GPL(nf_ct_l3protos);
static DEFINE_MUTEX(nf_ct_proto_mutex);
#ifdef CONFIG_SYSCTL
-static int
-nf_ct_register_sysctl(struct ctl_table_header **header, struct ctl_path *path,
- struct ctl_table *table, unsigned int *users)
+int
+nf_ct_register_net_sysctl(struct net *net,
+ struct ctl_table_header **header,
+ struct ctl_path *path,
+ struct ctl_table *table,
+ unsigned int *users)
{
if (*header == NULL) {
- *header = register_sysctl_paths(path, table);
+ *header = register_net_sysctl_table(net, path, table);
if (*header == NULL)
return -ENOMEM;
}
@@ -48,17 +51,21 @@ nf_ct_register_sysctl(struct ctl_table_header **header, struct ctl_path *path,
(*users)++;
return 0;
}
+EXPORT_SYMBOL_GPL(nf_ct_register_net_sysctl);
-static void
-nf_ct_unregister_sysctl(struct ctl_table_header **header,
- struct ctl_table *table, unsigned int *users)
+void
+nf_ct_unregister_net_sysctl(struct ctl_table_header **header,
+ struct ctl_table *table,
+ unsigned int *users)
{
if (users != NULL && --*users > 0)
return;
unregister_sysctl_table(*header);
+ kfree(table);
*header = NULL;
}
+EXPORT_SYMBOL_GPL(nf_ct_unregister_net_sysctl);
#endif
struct nf_conntrack_l4proto *
@@ -161,29 +168,6 @@ static int kill_l4proto(struct nf_conn *i, void *data)
nf_ct_l3num(i) == l4proto->l3proto;
}
-static int nf_ct_l3proto_register_sysctl(struct nf_conntrack_l3proto *l3proto)
-{
- int err = 0;
-
-#ifdef CONFIG_SYSCTL
- if (l3proto->ctl_table != NULL) {
- err = nf_ct_register_sysctl(&l3proto->ctl_table_header,
- l3proto->ctl_table_path,
- l3proto->ctl_table, NULL);
- }
-#endif
- return err;
-}
-
-static void nf_ct_l3proto_unregister_sysctl(struct nf_conntrack_l3proto *l3proto)
-{
-#ifdef CONFIG_SYSCTL
- if (l3proto->ctl_table_header != NULL)
- nf_ct_unregister_sysctl(&l3proto->ctl_table_header,
- l3proto->ctl_table, NULL);
-#endif
-}
-
int nf_conntrack_l3proto_register(struct nf_conntrack_l3proto *proto)
{
int ret = 0;
@@ -203,10 +187,6 @@ int nf_conntrack_l3proto_register(struct nf_conntrack_l3proto *proto)
goto out_unlock;
}
- ret = nf_ct_l3proto_register_sysctl(proto);
- if (ret < 0)
- goto out_unlock;
-
if (proto->nlattr_tuple_size)
proto->nla_size = 3 * proto->nlattr_tuple_size();
@@ -230,7 +210,6 @@ void nf_conntrack_l3proto_unregister(struct nf_conntrack_l3proto *proto)
) != proto);
rcu_assign_pointer(nf_ct_l3protos[proto->l3proto],
&nf_conntrack_l3proto_generic);
- nf_ct_l3proto_unregister_sysctl(proto);
mutex_unlock(&nf_ct_proto_mutex);
synchronize_rcu();
@@ -243,52 +222,6 @@ void nf_conntrack_l3proto_unregister(struct nf_conntrack_l3proto *proto)
}
EXPORT_SYMBOL_GPL(nf_conntrack_l3proto_unregister);
-static int nf_ct_l4proto_register_sysctl(struct nf_conntrack_l4proto *l4proto)
-{
- int err = 0;
-
-#ifdef CONFIG_SYSCTL
- if (l4proto->ctl_table != NULL) {
- err = nf_ct_register_sysctl(l4proto->ctl_table_header,
- nf_net_netfilter_sysctl_path,
- l4proto->ctl_table,
- l4proto->ctl_table_users);
- if (err < 0)
- goto out;
- }
-#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT
- if (l4proto->ctl_compat_table != NULL) {
- err = nf_ct_register_sysctl(&l4proto->ctl_compat_table_header,
- nf_net_ipv4_netfilter_sysctl_path,
- l4proto->ctl_compat_table, NULL);
- if (err == 0)
- goto out;
- nf_ct_unregister_sysctl(l4proto->ctl_table_header,
- l4proto->ctl_table,
- l4proto->ctl_table_users);
- }
-#endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */
-out:
-#endif /* CONFIG_SYSCTL */
- return err;
-}
-
-static void nf_ct_l4proto_unregister_sysctl(struct nf_conntrack_l4proto *l4proto)
-{
-#ifdef CONFIG_SYSCTL
- if (l4proto->ctl_table_header != NULL &&
- *l4proto->ctl_table_header != NULL)
- nf_ct_unregister_sysctl(l4proto->ctl_table_header,
- l4proto->ctl_table,
- l4proto->ctl_table_users);
-#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT
- if (l4proto->ctl_compat_table_header != NULL)
- nf_ct_unregister_sysctl(&l4proto->ctl_compat_table_header,
- l4proto->ctl_compat_table, NULL);
-#endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */
-#endif /* CONFIG_SYSCTL */
-}
-
/* FIXME: Allow NULL functions and sub in pointers to generic for
them. --RR */
int nf_conntrack_l4proto_register(struct nf_conntrack_l4proto *l4proto)
@@ -333,10 +266,6 @@ int nf_conntrack_l4proto_register(struct nf_conntrack_l4proto *l4proto)
goto out_unlock;
}
- ret = nf_ct_l4proto_register_sysctl(l4proto);
- if (ret < 0)
- goto out_unlock;
-
l4proto->nla_size = 0;
if (l4proto->nlattr_size)
l4proto->nla_size += l4proto->nlattr_size();
@@ -365,7 +294,6 @@ void nf_conntrack_l4proto_unregister(struct nf_conntrack_l4proto *l4proto)
) != l4proto);
rcu_assign_pointer(nf_ct_protos[l4proto->l3proto][l4proto->l4proto],
&nf_conntrack_l4proto_generic);
- nf_ct_l4proto_unregister_sysctl(l4proto);
mutex_unlock(&nf_ct_proto_mutex);
synchronize_rcu();
@@ -380,12 +308,7 @@ EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_unregister);
int nf_conntrack_proto_init(void)
{
- unsigned int i;
- int err;
-
- err = nf_ct_l4proto_register_sysctl(&nf_conntrack_l4proto_generic);
- if (err < 0)
- return err;
+ unsigned int i;
for (i = 0; i < AF_MAX; i++)
rcu_assign_pointer(nf_ct_l3protos[i],
@@ -397,8 +320,6 @@ void nf_conntrack_proto_fini(void)
{
unsigned int i;
- nf_ct_l4proto_unregister_sysctl(&nf_conntrack_l4proto_generic);
-
/* free l3proto protocol tables */
for (i = 0; i < PF_MAX; i++)
kfree(nf_ct_protos[i]);
--
1.7.7.6
^ permalink raw reply related
* [PATCH 01/12] netfilter: add struct netns_ct_proto to support netfilter namespace
From: Gao feng @ 2012-04-17 2:56 UTC (permalink / raw)
To: pablo; +Cc: netfilter-devel, netdev, ebiederm, serge.hallyn, dlezcano,
Gao feng
In-Reply-To: <1334631383-12326-1-git-send-email-gaofeng@cn.fujitsu.com>
the struct netns_ct_proto is used to store ctl_table_header and sysctl vars.
because udp_conntrack and udplite_conntrack are used by netns_ct_proto,
so move the udp_conntrack and udplite_conntrack to the header file,
Signed-off-by: Gao feng <gaofeng@cn.fujitsu.com>
---
include/linux/netfilter/nf_conntrack_udp.h | 10 ++++++
include/linux/netfilter/nf_conntrack_udplite.h | 10 ++++++
include/net/netns/conntrack.h | 37 ++++++++++++++++++++++++
3 files changed, 57 insertions(+), 0 deletions(-)
create mode 100644 include/linux/netfilter/nf_conntrack_udp.h
create mode 100644 include/linux/netfilter/nf_conntrack_udplite.h
diff --git a/include/linux/netfilter/nf_conntrack_udp.h b/include/linux/netfilter/nf_conntrack_udp.h
new file mode 100644
index 0000000..02869fc
--- /dev/null
+++ b/include/linux/netfilter/nf_conntrack_udp.h
@@ -0,0 +1,10 @@
+#ifndef _NF_CONNTRACK_UDP_H
+#define _NF_CONNTRACK_UDP_H
+
+enum udp_conntrack {
+ UDP_CT_UNREPLIED,
+ UDP_CT_REPLIED,
+ UDP_CT_MAX
+};
+
+#endif /* _NF_CONNTRACK_UDP_H */
diff --git a/include/linux/netfilter/nf_conntrack_udplite.h b/include/linux/netfilter/nf_conntrack_udplite.h
new file mode 100644
index 0000000..62b90a2
--- /dev/null
+++ b/include/linux/netfilter/nf_conntrack_udplite.h
@@ -0,0 +1,10 @@
+#ifndef _NF_CONNTRACK_UDPLITE_H
+#define _NF_CONNTRACK_UDPLITE_H
+
+enum udplite_conntrack {
+ UDPLITE_CT_UNREPLIED,
+ UDPLITE_CT_REPLIED,
+ UDPLITE_CT_MAX
+};
+
+#endif /* _NF_CONNTRACK_UDPLITE_H */
diff --git a/include/net/netns/conntrack.h b/include/net/netns/conntrack.h
index 7a911ec..5845665 100644
--- a/include/net/netns/conntrack.h
+++ b/include/net/netns/conntrack.h
@@ -4,10 +4,46 @@
#include <linux/list.h>
#include <linux/list_nulls.h>
#include <linux/atomic.h>
+#include <linux/netfilter/nf_conntrack_tcp.h>
+#include <linux/netfilter/nf_conntrack_udp.h>
+#include <linux/netfilter/nf_conntrack_udplite.h>
+#include <linux/netfilter/nf_conntrack_sctp.h>
struct ctl_table_header;
struct nf_conntrack_ecache;
+struct netns_ct_proto {
+ unsigned int sysctl_generic_timeout;
+ unsigned int sysctl_tcp_timeouts[TCP_CONNTRACK_TIMEOUT_MAX];
+ unsigned int sysctl_tcp_loose;
+ unsigned int sysctl_tcp_be_liberal;
+ unsigned int sysctl_tcp_max_retrans;
+ unsigned int sysctl_udp_timeouts[UDP_CT_MAX];
+ unsigned int sysctl_udplite_timeouts[UDPLITE_CT_MAX];
+ unsigned int sysctl_sctp_timeouts[SCTP_CONNTRACK_MAX];
+ unsigned int sysctl_icmp_timeout;
+ unsigned int sysctl_icmpv6_timeout;
+#ifdef CONFIG_SYSCTL
+ struct ctl_table_header *generic_sysctl_header;
+ struct ctl_table_header *tcp_sysctl_header;
+ struct ctl_table_header *udp_sysctl_header;
+ struct ctl_table_header *udplite_sysctl_header;
+ struct ctl_table_header *sctp_sysctl_header;
+ struct ctl_table_header *icmp_sysctl_header;
+ struct ctl_table_header *icmpv6_sysctl_header;
+ unsigned int tcp_table_users;
+ unsigned int udp_table_users;
+#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT
+ struct ctl_table_header *generic_compat_header;
+ struct ctl_table_header *tcp_compat_header;
+ struct ctl_table_header *udp_compat_header;
+ struct ctl_table_header *sctp_compat_header;
+ struct ctl_table_header *icmp_compat_header;
+ struct ctl_table_header *ipv4_compat_header;
+#endif
+#endif
+};
+
struct netns_ct {
atomic_t count;
unsigned int expect_count;
@@ -26,6 +62,7 @@ struct netns_ct {
int sysctl_tstamp;
int sysctl_checksum;
unsigned int sysctl_log_invalid; /* Log invalid packets */
+ struct netns_ct_proto proto;
#ifdef CONFIG_SYSCTL
struct ctl_table_header *sysctl_header;
struct ctl_table_header *acct_sysctl_header;
--
1.7.7.6
^ permalink raw reply related
* Re: 3.3.0, 3.4-rc1 reproducible tun Oops
From: Simon Kirby @ 2012-04-17 2:08 UTC (permalink / raw)
To: Eric Dumazet, Stanislav Kinsbursky; +Cc: netdev
In-Reply-To: <1333593664.18626.577.camel@edumazet-glaptop>
On Thu, Apr 05, 2012 at 04:41:04AM +0200, Eric Dumazet wrote:
> Hmm, is it happening if you remove the nvidia module ?
>
> If yes, please try to add slub_debug=FZPU
Finally got annoyed enough at this to bisect it. It doesn't happen every
time and I got a bit confused, but I finally tracked it down to:
1ab5ecb90cb6a3df1476e052f76a6e8f6511cb3d is the first bad commit
commit 1ab5ecb90cb6a3df1476e052f76a6e8f6511cb3d
Author: Stanislav Kinsbursky <skinsbursky@parallels.com>
Date: Mon Mar 12 02:59:41 2012 +0000
tun: don't hold network namespace by tun sockets
v3: added previously removed sock_put() to the tun_release() callback, because
sk_release_kernel() doesn't drop the socket reference.
v2: sk_release_kernel() used for socket release. Dummy tun_release() is
required for sk_release_kernel() ---> sock_release() ---> sock->ops->release()
call.
TUN was designed to destroy it's socket on network namesapce shutdown. But this
will never happen for persistent device, because it's socket holds network
namespace.
This patch removes of holding network namespace by TUN socket and replaces it
by creating socket in init_net and then changing it's net it to desired one. On
shutdown socket is moved back to init_net prior to final put.
Signed-off-by: Stanislav Kinsbursky <skinsbursky@parallels.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
...With this reverted on top of 3.4-rc3, I no longer see crashes when I
keep making and breaking the SSH tunnel while running "vmstat 1" in an
SSH session over a socket that is running through that tunnel.
Simon-
^ permalink raw reply
* [PATCH] net/ipv4:Remove two memleak reports by kmemeleak_not_leak
From: majianpeng @ 2012-04-17 1:41 UTC (permalink / raw)
To: eric.dumazet; +Cc: netdev
>From 582ed93b990e88110287ed0388bcb9057b1b8591 Mon Sep 17 00:00:00 2001
From: majianpeng <majianpeng@gmail.com>
Date: Tue, 17 Apr 2012 09:36:26 +0800
Subject: [PATCH] net/ipv4:Remove two memleak reports by kmemeleak_not_leak.
Signed-off-by: majianpeng <majianpeng@gmail.com>
---
net/ipv4/route.c | 8 ++++++--
1 files changed, 6 insertions(+), 2 deletions(-)
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index 167ea10..1984c82 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -3504,7 +3504,11 @@ int __init ip_rt_init(void)
* this nonsense will go away.
*/
void __init ip_static_sysctl_init(void)
-{
- register_sysctl_paths(ipv4_path, ipv4_skeleton);
+{
+ struct ctl_table_header *ctl_header;
+
+ ctl_header = register_sysctl_paths(ipv4_path, ipv4_skeleton);
+ if (ctl_header)
+ kmemleak_not_leak(ctl_header);
}
#endif
--
1.7.5.4
--------------
majianpeng
2012-04-17
^ permalink raw reply related
* [PATCH v3 1/3] netdev/of/phy: New function: of_mdio_find_bus().
From: David Daney @ 2012-04-17 1:03 UTC (permalink / raw)
To: Grant Likely, Rob Herring, devicetree-discuss, David S. Miller,
netdev
Cc: linux-kernel, linux-mips, afleming, galak, David Daney,
Grant Likely, David S. Miller
In-Reply-To: <1334624608-26667-1-git-send-email-ddaney.cavm@gmail.com>
From: David Daney <david.daney@cavium.com>
Add of_mdio_find_bus() which allows an mii_bus to be located given its
associated the device tree node.
This is needed by the follow-on patch to add a driver for MDIO bus
multiplexers.
The of_mdiobus_register() function is modified so that the device tree
node is recorded in the mii_bus. Then we can find it again by
iterating over all mdio_bus_class devices.
Because the OF device tree has now become an integral part of the
kernel, this can live in mdio_bus.c (which contains the needed
mdio_bus_class structure) instead of of_mdio.c.
Signed-off-by: David Daney <david.daney@cavium.com>
Cc: Grant Likely <grant.likely@secretlab.ca>
Cc: "David S. Miller" <davem@davemloft.net>
---
drivers/net/phy/mdio_bus.c | 32 ++++++++++++++++++++++++++++++++
drivers/of/of_mdio.c | 2 ++
include/linux/of_mdio.h | 2 ++
3 files changed, 36 insertions(+), 0 deletions(-)
diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c
index 8985cc6..46e7dc5 100644
--- a/drivers/net/phy/mdio_bus.c
+++ b/drivers/net/phy/mdio_bus.c
@@ -88,6 +88,38 @@ static struct class mdio_bus_class = {
.dev_release = mdiobus_release,
};
+#ifdef CONFIG_OF_MDIO
+/* Helper function for of_phy_find_device */
+static int of_mii_bus_match(struct device *dev, void *mii_bus_np)
+{
+ return dev->of_node == mii_bus_np;
+}
+/**
+ * of_mdio_find_bus - Given an mii_bus node, find the mii_bus.
+ * @mdio_np: Pointer to the mii_bus.
+ *
+ * Returns a pointer to the mii_bus, or NULL if none found.
+ *
+ * Because the association of a device_node and mii_bus is made via
+ * of_mdiobus_register(), the mii_bus cannot be found before it is
+ * registered with of_mdiobus_register().
+ *
+ */
+struct mii_bus *of_mdio_find_bus(struct device_node *mdio_np)
+{
+ struct device *d;
+
+ if (!mdio_np)
+ return NULL;
+
+ d = class_find_device(&mdio_bus_class, NULL, mdio_np,
+ of_mii_bus_match);
+
+ return d ? to_mii_bus(d) : NULL;
+}
+EXPORT_SYMBOL(of_mdio_find_bus);
+#endif
+
/**
* mdiobus_register - bring up all the PHYs on a given bus and attach them to bus
* @bus: target mii_bus
diff --git a/drivers/of/of_mdio.c b/drivers/of/of_mdio.c
index 483c0ad..2574abd 100644
--- a/drivers/of/of_mdio.c
+++ b/drivers/of/of_mdio.c
@@ -45,6 +45,8 @@ int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np)
for (i=0; i<PHY_MAX_ADDR; i++)
mdio->irq[i] = PHY_POLL;
+ mdio->dev.of_node = np;
+
/* Register the MDIO bus */
rc = mdiobus_register(mdio);
if (rc)
diff --git a/include/linux/of_mdio.h b/include/linux/of_mdio.h
index 53b94e0..912c27a 100644
--- a/include/linux/of_mdio.h
+++ b/include/linux/of_mdio.h
@@ -22,4 +22,6 @@ extern struct phy_device *of_phy_connect_fixed_link(struct net_device *dev,
void (*hndlr)(struct net_device *),
phy_interface_t iface);
+extern struct mii_bus *of_mdio_find_bus(struct device_node *mdio_np);
+
#endif /* __LINUX_OF_MDIO_H */
--
1.7.2.3
^ permalink raw reply related
* [PATCH v3 3/3] netdev/of/phy: Add MDIO bus multiplexer driven by GPIO lines.
From: David Daney @ 2012-04-17 1:03 UTC (permalink / raw)
To: Grant Likely, Rob Herring, devicetree-discuss, David S. Miller,
netdev
Cc: linux-kernel, linux-mips, afleming, galak, David Daney
In-Reply-To: <1334624608-26667-1-git-send-email-ddaney.cavm@gmail.com>
From: David Daney <david.daney@cavium.com>
The GPIO pins select which sub bus is connected to the master.
Initially tested with an sn74cbtlv3253 switch device wired into the
MDIO bus.
Signed-off-by: David Daney <david.daney@cavium.com>
---
.../devicetree/bindings/net/mdio-mux-gpio.txt | 127 +++++++++++++++++
drivers/net/phy/Kconfig | 10 ++
drivers/net/phy/Makefile | 1 +
drivers/net/phy/mdio-mux-gpio.c | 142 ++++++++++++++++++++
4 files changed, 280 insertions(+), 0 deletions(-)
create mode 100644 Documentation/devicetree/bindings/net/mdio-mux-gpio.txt
create mode 100644 drivers/net/phy/mdio-mux-gpio.c
diff --git a/Documentation/devicetree/bindings/net/mdio-mux-gpio.txt b/Documentation/devicetree/bindings/net/mdio-mux-gpio.txt
new file mode 100644
index 0000000..7938411
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/mdio-mux-gpio.txt
@@ -0,0 +1,127 @@
+Properties for an MDIO bus multiplexer/switch controlled by GPIO pins.
+
+This is a special case of a MDIO bus multiplexer. One or more GPIO
+lines are used to control which child bus is connected.
+
+Required properties in addition to the generic multiplexer properties:
+
+- compatible : mdio-mux-gpio.
+- gpios : GPIO specifiers for each GPIO line. One or more must be specified.
+
+
+Example :
+
+ /* The parent MDIO bus. */
+ smi1: mdio@1180000001900 {
+ compatible = "cavium,octeon-3860-mdio";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x11800 0x00001900 0x0 0x40>;
+ };
+
+ /*
+ An NXP sn74cbtlv3253 dual 1-of-4 switch controlled by a
+ pair of GPIO lines. Child busses 2 and 3 populated with 4
+ PHYs each.
+ */
+ mdio-mux {
+ compatible = "mdio-mux-gpio";
+ gpios = <&gpio1 3 0>, <&gpio1 4 0>;
+ mdio-parent-bus = <&smi1>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ mdio@2 {
+ reg = <2>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ phy11: ethernet-phy@1 {
+ reg = <1>;
+ compatible = "marvell,88e1149r";
+ marvell,reg-init = <3 0x10 0 0x5777>,
+ <3 0x11 0 0x00aa>,
+ <3 0x12 0 0x4105>,
+ <3 0x13 0 0x0a60>;
+ interrupt-parent = <&gpio>;
+ interrupts = <10 8>; /* Pin 10, active low */
+ };
+ phy12: ethernet-phy@2 {
+ reg = <2>;
+ compatible = "marvell,88e1149r";
+ marvell,reg-init = <3 0x10 0 0x5777>,
+ <3 0x11 0 0x00aa>,
+ <3 0x12 0 0x4105>,
+ <3 0x13 0 0x0a60>;
+ interrupt-parent = <&gpio>;
+ interrupts = <10 8>; /* Pin 10, active low */
+ };
+ phy13: ethernet-phy@3 {
+ reg = <3>;
+ compatible = "marvell,88e1149r";
+ marvell,reg-init = <3 0x10 0 0x5777>,
+ <3 0x11 0 0x00aa>,
+ <3 0x12 0 0x4105>,
+ <3 0x13 0 0x0a60>;
+ interrupt-parent = <&gpio>;
+ interrupts = <10 8>; /* Pin 10, active low */
+ };
+ phy14: ethernet-phy@4 {
+ reg = <4>;
+ compatible = "marvell,88e1149r";
+ marvell,reg-init = <3 0x10 0 0x5777>,
+ <3 0x11 0 0x00aa>,
+ <3 0x12 0 0x4105>,
+ <3 0x13 0 0x0a60>;
+ interrupt-parent = <&gpio>;
+ interrupts = <10 8>; /* Pin 10, active low */
+ };
+ };
+
+ mdio@3 {
+ reg = <3>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ phy21: ethernet-phy@1 {
+ reg = <1>;
+ compatible = "marvell,88e1149r";
+ marvell,reg-init = <3 0x10 0 0x5777>,
+ <3 0x11 0 0x00aa>,
+ <3 0x12 0 0x4105>,
+ <3 0x13 0 0x0a60>;
+ interrupt-parent = <&gpio>;
+ interrupts = <12 8>; /* Pin 12, active low */
+ };
+ phy22: ethernet-phy@2 {
+ reg = <2>;
+ compatible = "marvell,88e1149r";
+ marvell,reg-init = <3 0x10 0 0x5777>,
+ <3 0x11 0 0x00aa>,
+ <3 0x12 0 0x4105>,
+ <3 0x13 0 0x0a60>;
+ interrupt-parent = <&gpio>;
+ interrupts = <12 8>; /* Pin 12, active low */
+ };
+ phy23: ethernet-phy@3 {
+ reg = <3>;
+ compatible = "marvell,88e1149r";
+ marvell,reg-init = <3 0x10 0 0x5777>,
+ <3 0x11 0 0x00aa>,
+ <3 0x12 0 0x4105>,
+ <3 0x13 0 0x0a60>;
+ interrupt-parent = <&gpio>;
+ interrupts = <12 8>; /* Pin 12, active low */
+ };
+ phy24: ethernet-phy@4 {
+ reg = <4>;
+ compatible = "marvell,88e1149r";
+ marvell,reg-init = <3 0x10 0 0x5777>,
+ <3 0x11 0 0x00aa>,
+ <3 0x12 0 0x4105>,
+ <3 0x13 0 0x0a60>;
+ interrupt-parent = <&gpio>;
+ interrupts = <12 8>; /* Pin 12, active low */
+ };
+ };
+ };
diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
index 222b06b..39d8c66 100644
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -143,6 +143,16 @@ config MDIO_BUS_MUX
to a parent bus. Switching between child busses is done by
device specific drivers.
+config MDIO_BUS_MUX_GPIO
+ tristate "Support for GPIO controlled MDIO bus multiplexers"
+ depends on GENERIC_GPIO
+ select MDIO_BUS_MUX
+ help
+ This module provides a driver for MDIO bus multiplexers that
+ are controlled via GPIO lines. The multiplexer connects one of
+ several child MDIO busses to a parent bus. Child bus
+ selection is under the control of GPIO lines.
+
endif # PHYLIB
config MICREL_KS8995MA
diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
index a6b50e7..f51af68 100644
--- a/drivers/net/phy/Makefile
+++ b/drivers/net/phy/Makefile
@@ -26,3 +26,4 @@ obj-$(CONFIG_MDIO_OCTEON) += mdio-octeon.o
obj-$(CONFIG_MICREL_KS8995MA) += spi_ks8995.o
obj-$(CONFIG_AMD_PHY) += amd.o
obj-$(CONFIG_MDIO_BUS_MUX) += mdio-mux.o
+obj-$(CONFIG_MDIO_BUS_MUX_GPIO) += mdio-mux-gpio.o
diff --git a/drivers/net/phy/mdio-mux-gpio.c b/drivers/net/phy/mdio-mux-gpio.c
new file mode 100644
index 0000000..e0cc4ef
--- /dev/null
+++ b/drivers/net/phy/mdio-mux-gpio.c
@@ -0,0 +1,142 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2011, 2012 Cavium, Inc.
+ */
+
+#include <linux/platform_device.h>
+#include <linux/device.h>
+#include <linux/of_mdio.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/phy.h>
+#include <linux/mdio-mux.h>
+#include <linux/of_gpio.h>
+
+#define DRV_VERSION "1.0"
+#define DRV_DESCRIPTION "GPIO controlled MDIO bus multiplexer driver"
+
+#define MDIO_MUX_GPIO_MAX_BITS 8
+
+struct mdio_mux_gpio_state {
+ int gpio[MDIO_MUX_GPIO_MAX_BITS];
+ unsigned int num_gpios;
+ void *mux_handle;
+};
+
+static int mdio_mux_gpio_switch_fn(int current_child, int desired_child,
+ void *data)
+{
+ int change;
+ unsigned int n;
+ struct mdio_mux_gpio_state *s = data;
+
+ if (current_child == desired_child)
+ return 0;
+
+ change = current_child == -1 ? -1 : current_child ^ desired_child;
+
+ for (n = 0; n < s->num_gpios; n++) {
+ if (change & 1)
+ gpio_set_value_cansleep(s->gpio[n],
+ (desired_child & 1) != 0);
+ change >>= 1;
+ desired_child >>= 1;
+ }
+
+ return 0;
+}
+
+static int __devinit mdio_mux_gpio_probe(struct platform_device *pdev)
+{
+ enum of_gpio_flags f;
+ struct mdio_mux_gpio_state *s;
+ unsigned int num_gpios;
+ unsigned int n;
+ int r;
+
+ if (!pdev->dev.of_node)
+ return -ENODEV;
+
+ num_gpios = of_gpio_count(pdev->dev.of_node);
+ if (num_gpios == 0 || num_gpios > MDIO_MUX_GPIO_MAX_BITS)
+ return -ENODEV;
+
+ s = devm_kzalloc(&pdev->dev, sizeof(*s), GFP_KERNEL);
+ if (!s)
+ return -ENOMEM;
+
+ s->num_gpios = num_gpios;
+
+ for (n = 0; n < num_gpios; ) {
+ int gpio = of_get_gpio_flags(pdev->dev.of_node, n, &f);
+ if (gpio < 0) {
+ r = (gpio == -ENODEV) ? -EPROBE_DEFER : gpio;
+ goto err;
+ }
+ s->gpio[n] = gpio;
+
+ n++;
+
+ r = gpio_request(gpio, "mdio_mux_gpio");
+ if (r)
+ goto err;
+
+ r = gpio_direction_output(gpio, 0);
+ if (r)
+ goto err;
+ }
+
+ r = mdio_mux_init(&pdev->dev,
+ mdio_mux_gpio_switch_fn, &s->mux_handle, s);
+
+ if (r == 0) {
+ pdev->dev.platform_data = s;
+ return 0;
+ }
+err:
+ while (n) {
+ n--;
+ gpio_free(s->gpio[n]);
+ }
+ devm_kfree(&pdev->dev, s);
+ return r;
+}
+
+static int __devexit mdio_mux_gpio_remove(struct platform_device *pdev)
+{
+ struct mdio_mux_gpio_state *s = pdev->dev.platform_data;
+ mdio_mux_uninit(s->mux_handle);
+ return 0;
+}
+
+static struct of_device_id mdio_mux_gpio_match[] = {
+ {
+ .compatible = "mdio-mux-gpio",
+ },
+ {
+ /* Legacy compatible property. */
+ .compatible = "cavium,mdio-mux-sn74cbtlv3253",
+ },
+ {},
+};
+MODULE_DEVICE_TABLE(of, mdio_mux_gpio_match);
+
+static struct platform_driver mdio_mux_gpio_driver = {
+ .driver = {
+ .name = "mdio-mux-gpio",
+ .owner = THIS_MODULE,
+ .of_match_table = mdio_mux_gpio_match,
+ },
+ .probe = mdio_mux_gpio_probe,
+ .remove = __devexit_p(mdio_mux_gpio_remove),
+};
+
+module_platform_driver(mdio_mux_gpio_driver);
+
+MODULE_DESCRIPTION(DRV_DESCRIPTION);
+MODULE_VERSION(DRV_VERSION);
+MODULE_AUTHOR("David Daney");
+MODULE_LICENSE("GPL");
--
1.7.2.3
^ permalink raw reply related
* [PATCH v3 2/3] netdev/of/phy: Add MDIO bus multiplexer support.
From: David Daney @ 2012-04-17 1:03 UTC (permalink / raw)
To: Grant Likely, Rob Herring, devicetree-discuss, David S. Miller,
netdev
Cc: linux-kernel, linux-mips, afleming, galak, David Daney
In-Reply-To: <1334624608-26667-1-git-send-email-ddaney.cavm@gmail.com>
From: David Daney <david.daney@cavium.com>
This patch adds a somewhat generic framework for MDIO bus
multiplexers. It is modeled on the I2C multiplexer.
The multiplexer is needed if there are multiple PHYs with the same
address connected to the same MDIO bus adepter, or if there is
insufficient electrical drive capability for all the connected PHY
devices.
Conceptually it could look something like this:
------------------
| Control Signal |
--------+---------
|
--------------- --------+------
| MDIO MASTER |---| Multiplexer |
--------------- --+-------+----
| |
C C
h h
i i
l l
d d
| |
--------- A B ---------
| | | | | |
| PHY@1 +-------+ +---+ PHY@1 |
| | | | | |
--------- | | ---------
--------- | | ---------
| | | | | |
| PHY@2 +-------+ +---+ PHY@2 |
| | | |
--------- ---------
This framework configures the bus topology from device tree data. The
mechanics of switching the multiplexer is left to device specific
drivers.
The follow-on patch contains a multiplexer driven by GPIO lines.
Signed-off-by: David Daney <david.daney@cavium.com>
---
Documentation/devicetree/bindings/net/mdio-mux.txt | 136 ++++++++++++++
drivers/net/phy/Kconfig | 8 +
drivers/net/phy/Makefile | 1 +
drivers/net/phy/mdio-mux.c | 192 ++++++++++++++++++++
include/linux/mdio-mux.h | 21 ++
5 files changed, 358 insertions(+), 0 deletions(-)
create mode 100644 Documentation/devicetree/bindings/net/mdio-mux.txt
create mode 100644 drivers/net/phy/mdio-mux.c
create mode 100644 include/linux/mdio-mux.h
diff --git a/Documentation/devicetree/bindings/net/mdio-mux.txt b/Documentation/devicetree/bindings/net/mdio-mux.txt
new file mode 100644
index 0000000..f65606f
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/mdio-mux.txt
@@ -0,0 +1,136 @@
+Common MDIO bus multiplexer/switch properties.
+
+An MDIO bus multiplexer/switch will have several child busses that are
+numbered uniquely in a device dependent manner. The nodes for an MDIO
+bus multiplexer/switch will have one child node for each child bus.
+
+Required properties:
+- mdio-parent-bus : phandle to the parent MDIO bus.
+- #address-cells = <1>;
+- #size-cells = <0>;
+
+Optional properties:
+- Other properties specific to the multiplexer/switch hardware.
+
+Required properties for child nodes:
+- #address-cells = <1>;
+- #size-cells = <0>;
+- reg : The sub-bus number.
+
+
+Example :
+
+ /* The parent MDIO bus. */
+ smi1: mdio@1180000001900 {
+ compatible = "cavium,octeon-3860-mdio";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x11800 0x00001900 0x0 0x40>;
+ };
+
+ /*
+ An NXP sn74cbtlv3253 dual 1-of-4 switch controlled by a
+ pair of GPIO lines. Child busses 2 and 3 populated with 4
+ PHYs each.
+ */
+ mdio-mux {
+ compatible = "mdio-mux-gpio";
+ gpios = <&gpio1 3 0>, <&gpio1 4 0>;
+ mdio-parent-bus = <&smi1>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ mdio@2 {
+ reg = <2>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ phy11: ethernet-phy@1 {
+ reg = <1>;
+ compatible = "marvell,88e1149r";
+ marvell,reg-init = <3 0x10 0 0x5777>,
+ <3 0x11 0 0x00aa>,
+ <3 0x12 0 0x4105>,
+ <3 0x13 0 0x0a60>;
+ interrupt-parent = <&gpio>;
+ interrupts = <10 8>; /* Pin 10, active low */
+ };
+ phy12: ethernet-phy@2 {
+ reg = <2>;
+ compatible = "marvell,88e1149r";
+ marvell,reg-init = <3 0x10 0 0x5777>,
+ <3 0x11 0 0x00aa>,
+ <3 0x12 0 0x4105>,
+ <3 0x13 0 0x0a60>;
+ interrupt-parent = <&gpio>;
+ interrupts = <10 8>; /* Pin 10, active low */
+ };
+ phy13: ethernet-phy@3 {
+ reg = <3>;
+ compatible = "marvell,88e1149r";
+ marvell,reg-init = <3 0x10 0 0x5777>,
+ <3 0x11 0 0x00aa>,
+ <3 0x12 0 0x4105>,
+ <3 0x13 0 0x0a60>;
+ interrupt-parent = <&gpio>;
+ interrupts = <10 8>; /* Pin 10, active low */
+ };
+ phy14: ethernet-phy@4 {
+ reg = <4>;
+ compatible = "marvell,88e1149r";
+ marvell,reg-init = <3 0x10 0 0x5777>,
+ <3 0x11 0 0x00aa>,
+ <3 0x12 0 0x4105>,
+ <3 0x13 0 0x0a60>;
+ interrupt-parent = <&gpio>;
+ interrupts = <10 8>; /* Pin 10, active low */
+ };
+ };
+
+ mdio@3 {
+ reg = <3>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ phy21: ethernet-phy@1 {
+ reg = <1>;
+ compatible = "marvell,88e1149r";
+ marvell,reg-init = <3 0x10 0 0x5777>,
+ <3 0x11 0 0x00aa>,
+ <3 0x12 0 0x4105>,
+ <3 0x13 0 0x0a60>;
+ interrupt-parent = <&gpio>;
+ interrupts = <12 8>; /* Pin 12, active low */
+ };
+ phy22: ethernet-phy@2 {
+ reg = <2>;
+ compatible = "marvell,88e1149r";
+ marvell,reg-init = <3 0x10 0 0x5777>,
+ <3 0x11 0 0x00aa>,
+ <3 0x12 0 0x4105>,
+ <3 0x13 0 0x0a60>;
+ interrupt-parent = <&gpio>;
+ interrupts = <12 8>; /* Pin 12, active low */
+ };
+ phy23: ethernet-phy@3 {
+ reg = <3>;
+ compatible = "marvell,88e1149r";
+ marvell,reg-init = <3 0x10 0 0x5777>,
+ <3 0x11 0 0x00aa>,
+ <3 0x12 0 0x4105>,
+ <3 0x13 0 0x0a60>;
+ interrupt-parent = <&gpio>;
+ interrupts = <12 8>; /* Pin 12, active low */
+ };
+ phy24: ethernet-phy@4 {
+ reg = <4>;
+ compatible = "marvell,88e1149r";
+ marvell,reg-init = <3 0x10 0 0x5777>,
+ <3 0x11 0 0x00aa>,
+ <3 0x12 0 0x4105>,
+ <3 0x13 0 0x0a60>;
+ interrupt-parent = <&gpio>;
+ interrupts = <12 8>; /* Pin 12, active low */
+ };
+ };
+ };
diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
index 0e01f4e..222b06b 100644
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -135,6 +135,14 @@ config MDIO_OCTEON
If in doubt, say Y.
+config MDIO_BUS_MUX
+ tristate
+ help
+ This module provides a driver framework for MDIO bus
+ multiplexers which connect one of several child MDIO busses
+ to a parent bus. Switching between child busses is done by
+ device specific drivers.
+
endif # PHYLIB
config MICREL_KS8995MA
diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
index b7438b1..a6b50e7 100644
--- a/drivers/net/phy/Makefile
+++ b/drivers/net/phy/Makefile
@@ -25,3 +25,4 @@ obj-$(CONFIG_MICREL_PHY) += micrel.o
obj-$(CONFIG_MDIO_OCTEON) += mdio-octeon.o
obj-$(CONFIG_MICREL_KS8995MA) += spi_ks8995.o
obj-$(CONFIG_AMD_PHY) += amd.o
+obj-$(CONFIG_MDIO_BUS_MUX) += mdio-mux.o
diff --git a/drivers/net/phy/mdio-mux.c b/drivers/net/phy/mdio-mux.c
new file mode 100644
index 0000000..39ea067
--- /dev/null
+++ b/drivers/net/phy/mdio-mux.c
@@ -0,0 +1,192 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2011, 2012 Cavium, Inc.
+ */
+
+#include <linux/platform_device.h>
+#include <linux/mdio-mux.h>
+#include <linux/of_mdio.h>
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/phy.h>
+
+#define DRV_VERSION "1.0"
+#define DRV_DESCRIPTION "MDIO bus multiplexer driver"
+
+struct mdio_mux_child_bus;
+
+struct mdio_mux_parent_bus {
+ struct mii_bus *mii_bus;
+ int current_child;
+ int parent_id;
+ void *switch_data;
+ int (*switch_fn)(int current_child, int desired_child, void *data);
+
+ /* List of our children linked through their next fields. */
+ struct mdio_mux_child_bus *children;
+};
+
+struct mdio_mux_child_bus {
+ struct mii_bus *mii_bus;
+ struct mdio_mux_parent_bus *parent;
+ struct mdio_mux_child_bus *next;
+ int bus_number;
+ int phy_irq[PHY_MAX_ADDR];
+};
+
+/*
+ * The parent bus' lock is used to order access to the switch_fn.
+ */
+static int mdio_mux_read(struct mii_bus *bus, int phy_id, int regnum)
+{
+ struct mdio_mux_child_bus *cb = bus->priv;
+ struct mdio_mux_parent_bus *pb = cb->parent;
+ int r;
+
+ mutex_lock(&pb->mii_bus->mdio_lock);
+ r = pb->switch_fn(pb->current_child, cb->bus_number, pb->switch_data);
+ if (r)
+ goto out;
+
+ pb->current_child = cb->bus_number;
+
+ r = pb->mii_bus->read(pb->mii_bus, phy_id, regnum);
+out:
+ mutex_unlock(&pb->mii_bus->mdio_lock);
+
+ return r;
+}
+
+/*
+ * The parent bus' lock is used to order access to the switch_fn.
+ */
+static int mdio_mux_write(struct mii_bus *bus, int phy_id,
+ int regnum, u16 val)
+{
+ struct mdio_mux_child_bus *cb = bus->priv;
+ struct mdio_mux_parent_bus *pb = cb->parent;
+
+ int r;
+
+ mutex_lock(&pb->mii_bus->mdio_lock);
+ r = pb->switch_fn(pb->current_child, cb->bus_number, pb->switch_data);
+ if (r)
+ goto out;
+
+ pb->current_child = cb->bus_number;
+
+ r = pb->mii_bus->write(pb->mii_bus, phy_id, regnum, val);
+out:
+ mutex_unlock(&pb->mii_bus->mdio_lock);
+
+ return r;
+}
+
+static int parent_count;
+
+int mdio_mux_init(struct device *dev,
+ int (*switch_fn)(int cur, int desired, void *data),
+ void **mux_handle,
+ void *data)
+{
+ struct device_node *parent_bus_node;
+ struct device_node *child_bus_node;
+ int r, ret_val;
+ struct mii_bus *parent_bus;
+ struct mdio_mux_parent_bus *pb;
+ struct mdio_mux_child_bus *cb;
+
+ if (!dev->of_node)
+ return -ENODEV;
+
+ parent_bus_node = of_parse_phandle(dev->of_node, "mdio-parent-bus", 0);
+
+ if (!parent_bus_node)
+ return -ENODEV;
+
+ parent_bus = of_mdio_find_bus(parent_bus_node);
+ if (parent_bus == NULL) {
+ ret_val = -EPROBE_DEFER;
+ goto err_parent_bus;
+ }
+
+ pb = devm_kzalloc(dev, sizeof(*pb), GFP_KERNEL);
+ if (pb == NULL) {
+ ret_val = -ENOMEM;
+ goto err_parent_bus;
+ }
+
+ pb->switch_data = data;
+ pb->switch_fn = switch_fn;
+ pb->current_child = -1;
+ pb->parent_id = parent_count++;
+ pb->mii_bus = parent_bus;
+
+ ret_val = -ENODEV;
+ for_each_child_of_node(dev->of_node, child_bus_node) {
+ u32 v;
+
+ r = of_property_read_u32(child_bus_node, "reg", &v);
+ if (r)
+ continue;
+
+ cb = devm_kzalloc(dev, sizeof(*cb), GFP_KERNEL);
+ if (cb == NULL) {
+ dev_err(dev,
+ "Error: Failed to allocate memory for child\n");
+ ret_val = -ENOMEM;
+ break;
+ }
+ cb->bus_number = v;
+ cb->parent = pb;
+ cb->mii_bus = mdiobus_alloc();
+ cb->mii_bus->priv = cb;
+
+ cb->mii_bus->irq = cb->phy_irq;
+ cb->mii_bus->name = "mdio_mux";
+ snprintf(cb->mii_bus->id, MII_BUS_ID_SIZE, "%x.%x",
+ pb->parent_id, v);
+ cb->mii_bus->parent = dev;
+ cb->mii_bus->read = mdio_mux_read;
+ cb->mii_bus->write = mdio_mux_write;
+ r = of_mdiobus_register(cb->mii_bus, child_bus_node);
+ if (r) {
+ mdiobus_free(cb->mii_bus);
+ devm_kfree(dev, cb);
+ } else {
+ of_node_get(child_bus_node);
+ cb->next = pb->children;
+ pb->children = cb;
+ }
+ }
+ if (pb->children) {
+ *mux_handle = pb;
+ dev_info(dev, "Version " DRV_VERSION "\n");
+ return 0;
+ }
+err_parent_bus:
+ of_node_put(parent_bus_node);
+ return ret_val;
+}
+EXPORT_SYMBOL_GPL(mdio_mux_init);
+
+void mdio_mux_uninit(void *mux_handle)
+{
+ struct mdio_mux_parent_bus *pb = mux_handle;
+ struct mdio_mux_child_bus *cb = pb->children;
+
+ while (cb) {
+ mdiobus_unregister(cb->mii_bus);
+ mdiobus_free(cb->mii_bus);
+ cb = cb->next;
+ }
+}
+EXPORT_SYMBOL_GPL(mdio_mux_uninit);
+
+MODULE_DESCRIPTION(DRV_DESCRIPTION);
+MODULE_VERSION(DRV_VERSION);
+MODULE_AUTHOR("David Daney");
+MODULE_LICENSE("GPL");
diff --git a/include/linux/mdio-mux.h b/include/linux/mdio-mux.h
new file mode 100644
index 0000000..a243dbb
--- /dev/null
+++ b/include/linux/mdio-mux.h
@@ -0,0 +1,21 @@
+/*
+ * MDIO bus multiplexer framwork.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2011, 2012 Cavium, Inc.
+ */
+#ifndef __LINUX_MDIO_MUX_H
+#define __LINUX_MDIO_MUX_H
+#include <linux/device.h>
+
+int mdio_mux_init(struct device *dev,
+ int (*switch_fn) (int cur, int desired, void *data),
+ void **mux_handle,
+ void *data);
+
+void mdio_mux_uninit(void *mux_handle);
+
+#endif /* __LINUX_MDIO_MUX_H */
--
1.7.2.3
^ permalink raw reply related
* [PATCH v3 0/3] netdev/of/phy: MDIO bus multiplexer support.
From: David Daney @ 2012-04-17 1:03 UTC (permalink / raw)
To: Grant Likely, Rob Herring,
devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ, David S. Miller,
netdev-u79uwXL29TY76Z2rM5mHXA
Cc: linux-mips-6z/3iImG2C8G8FEW9MqTrA,
afleming-Re5JQEeQqe8AvxtiuMwx3w, David Daney,
linux-kernel-u79uwXL29TY76Z2rM5mHXA
From: David Daney <david.daney-YGCgFSpz5w/QT0dZR+AlfA@public.gmane.org>
This code has been working well for about six months on a couple of
different configurations (boards), so I thought it would be a good
time to send it out again, and I hope get it on the path towards
merging.
v3: Update binding to use "mdio-mux-gpio" compatible property.
Cleanups suggested by Grant Likely. Now uses the driver probe
deferral mechanism if GPIOs or parent bus not available.
v2: Update bindings to use "reg" and "mdio-parent-bus" instead of
"cell-index" and "parent-bus"
v1:
We have several different boards with a multiplexer in the MDIO bus.
There is an MDIO bus controller connected to a switching device with
several child MDIO busses.
Everything is wired up using device tree bindings.
1/3 - New of_mdio_find_bus() function used to help configuring the
driver topology.
2/3 - MDIO bus multiplexer framework.
3/3 - A driver for a GPIO controlled multiplexer.
David Daney (3):
netdev/of/phy: New function: of_mdio_find_bus().
netdev/of/phy: Add MDIO bus multiplexer support.
netdev/of/phy: Add MDIO bus multiplexer driven by GPIO lines.
.../devicetree/bindings/net/mdio-mux-gpio.txt | 127 +++++++++++++
Documentation/devicetree/bindings/net/mdio-mux.txt | 136 ++++++++++++++
drivers/net/phy/Kconfig | 18 ++
drivers/net/phy/Makefile | 2 +
drivers/net/phy/mdio-mux-gpio.c | 142 +++++++++++++++
drivers/net/phy/mdio-mux.c | 192 ++++++++++++++++++++
drivers/net/phy/mdio_bus.c | 32 ++++
drivers/of/of_mdio.c | 2 +
include/linux/mdio-mux.h | 21 ++
include/linux/of_mdio.h | 2 +
10 files changed, 674 insertions(+), 0 deletions(-)
create mode 100644 Documentation/devicetree/bindings/net/mdio-mux-gpio.txt
create mode 100644 Documentation/devicetree/bindings/net/mdio-mux.txt
create mode 100644 drivers/net/phy/mdio-mux-gpio.c
create mode 100644 drivers/net/phy/mdio-mux.c
create mode 100644 include/linux/mdio-mux.h
--
1.7.2.3
^ permalink raw reply
* [PATCH -next] hippi: fix printk format in rrunner.c
From: Randy Dunlap @ 2012-04-17 1:01 UTC (permalink / raw)
To: Stephen Rothwell
Cc: linux-next, LKML, netdev, linux-hippi, Jes Sorensen,
Andrew Morton
In-Reply-To: <20120416161121.261ba4e7e38989173accfb16@canb.auug.org.au>
From: Randy Dunlap <rdunlap@xenotime.net>
Fix printk format warning (from i386 build):
drivers/net/hippi/rrunner.c:146:9: warning: format '%08llx' expects type 'long long unsigned int', but argument 3 has type 'resource_size_t'
Signed-off-by: Randy Dunlap <rdunlap@xenotime.net>
Cc: Jes Sorensen <jes@trained-monkey.org>
Cc: linux-hippi@sunsite.dk
---
drivers/net/hippi/rrunner.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
--- linux-next-20120416.orig/drivers/net/hippi/rrunner.c
+++ linux-next-20120416/drivers/net/hippi/rrunner.c
@@ -142,8 +142,9 @@ static int __devinit rr_init_one(struct
pci_set_master(pdev);
printk(KERN_INFO "%s: Essential RoadRunner serial HIPPI "
- "at 0x%08llx, irq %i, PCI latency %i\n", dev->name,
- pci_resource_start(pdev, 0), pdev->irq, pci_latency);
+ "at 0x%llx, irq %i, PCI latency %i\n", dev->name,
+ (unsigned long long)pci_resource_start(pdev, 0),
+ pdev->irq, pci_latency);
/*
* Remap the MMIO regs into kernel space.
^ permalink raw reply
* Re: Netlink, route monitoring, RTM_DELROUTE not issued for ppp peer address. Bug or feature?
From: Stephen Hemminger @ 2012-04-16 21:00 UTC (permalink / raw)
To: Stian Skjelstad
Cc: Denys Fedoryshchenko, eric.dumazet, stephen.hemminger, netdev
In-Reply-To: <2f6d1271c8c6811acbbc5b2603c72115.squirrel@nlc.no>
On Mon, 16 Apr 2012 22:21:46 +0200
"Stian Skjelstad" <stian@nixia.no> wrote:
> > It looks like "correct" behavior should not harm existing programs that
> > much (just there will be netlink message to delete route that are
> > already deleted by program, e.g. quagga), but looking to code,
> > implementing this feature will make significant overhead and in some
> > cases it can be harmful.
> > For example if full view BGP interface dropped, it is hundreds of
> > thousands netlink messages. So seems better i will listen to
> > address/link changes also and keep routing table in memory.
> > So better seems to keep as is.
>
> If I understand correct, the "missing" RTM_DELROUTE messages actually
> comes from something similar to "ip route flush dev eth0".
>
> If the amount of traffic is a worry, couldn't there be a RTM_FLUSHROUTE or
> a special RTM_DELROUTE message that tells that all routes for a given
> device is removed?
>
No. new message type would confuse all the things that listen now.
^ permalink raw reply
* Re: [PATCH 0/9] atl1: add napi to Atheros L1 NIC
From: Chris Snook @ 2012-04-16 20:51 UTC (permalink / raw)
To: Tony Zelenoff
Cc: David Miller, netdev@vger.kernel.org, jcliburn@gmail.com,
Konstantin Khorenko
In-Reply-To: <4F8BC8C3.6020102@parallels.com>
On Mon, Apr 16, 2012 at 12:22 AM, Tony Zelenoff <antonz@parallels.com> wrote:
> Also, i'm interested in what to do with Chris Nook address in contacts list.
> Reason - mailer respond that this address is not valid anymore. Should i
> remove him from contacts or leave?
>
> Mailer response:
>
> csnook@redhat.com
> SMTP error from remote mail server after RCPT TO:<csnook@redhat.com>:
> host mx1.redhat.com [209.132.183.28]: 550 5.2.1 <csnook@redhat.com>...
> Mailbox disabled for this recipient
MAINTAINERS is your friend :)
^ permalink raw reply
* Re: Netlink, route monitoring, RTM_DELROUTE not issued for ppp peer address. Bug or feature?
From: Stian Skjelstad @ 2012-04-16 20:21 UTC (permalink / raw)
To: Denys Fedoryshchenko
Cc: Stephen Hemminger, Stian Skjelstad, eric.dumazet,
stephen.hemminger, netdev
In-Reply-To: <9c375f4b88835bcde92bf3ba8f3434cc@visp.net.lb>
> It looks like "correct" behavior should not harm existing programs that
> much (just there will be netlink message to delete route that are
> already deleted by program, e.g. quagga), but looking to code,
> implementing this feature will make significant overhead and in some
> cases it can be harmful.
> For example if full view BGP interface dropped, it is hundreds of
> thousands netlink messages. So seems better i will listen to
> address/link changes also and keep routing table in memory.
> So better seems to keep as is.
If I understand correct, the "missing" RTM_DELROUTE messages actually
comes from something similar to "ip route flush dev eth0".
If the amount of traffic is a worry, couldn't there be a RTM_FLUSHROUTE or
a special RTM_DELROUTE message that tells that all routes for a given
device is removed?
Stian Skjelstad
^ 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