* [PATCH 06/10] netfilter: PTR_RET can be used
From: pablo @ 2012-08-22 23:38 UTC (permalink / raw)
To: netfilter-devel; +Cc: davem, netdev
In-Reply-To: <1345678726-3109-1-git-send-email-pablo@netfilter.org>
From: Wu Fengguang <fengguang.wu@intel.com>
This quiets the coccinelle warnings:
net/bridge/netfilter/ebtable_filter.c:107:1-3: WARNING: PTR_RET can be used
net/bridge/netfilter/ebtable_nat.c:107:1-3: WARNING: PTR_RET can be used
net/ipv6/netfilter/ip6table_filter.c:65:1-3: WARNING: PTR_RET can be used
net/ipv6/netfilter/ip6table_mangle.c:100:1-3: WARNING: PTR_RET can be used
net/ipv6/netfilter/ip6table_raw.c:44:1-3: WARNING: PTR_RET can be used
net/ipv6/netfilter/ip6table_security.c:62:1-3: WARNING: PTR_RET can be used
net/ipv4/netfilter/iptable_filter.c:72:1-3: WARNING: PTR_RET can be used
net/ipv4/netfilter/iptable_mangle.c:107:1-3: WARNING: PTR_RET can be used
net/ipv4/netfilter/iptable_raw.c:51:1-3: WARNING: PTR_RET can be used
net/ipv4/netfilter/iptable_security.c:70:1-3: WARNING: PTR_RET can be used
Signed-off-by: Fengguang Wu <fengguang.wu@intel.com>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
net/bridge/netfilter/ebtable_filter.c | 4 +---
net/bridge/netfilter/ebtable_nat.c | 4 +---
net/ipv4/netfilter/iptable_filter.c | 4 +---
net/ipv4/netfilter/iptable_mangle.c | 4 +---
net/ipv4/netfilter/iptable_raw.c | 4 +---
net/ipv4/netfilter/iptable_security.c | 5 +----
net/ipv6/netfilter/ip6table_filter.c | 4 +---
net/ipv6/netfilter/ip6table_mangle.c | 4 +---
net/ipv6/netfilter/ip6table_raw.c | 4 +---
net/ipv6/netfilter/ip6table_security.c | 5 +----
10 files changed, 10 insertions(+), 32 deletions(-)
diff --git a/net/bridge/netfilter/ebtable_filter.c b/net/bridge/netfilter/ebtable_filter.c
index 42e6bd0..3c2e9dc 100644
--- a/net/bridge/netfilter/ebtable_filter.c
+++ b/net/bridge/netfilter/ebtable_filter.c
@@ -100,9 +100,7 @@ static struct nf_hook_ops ebt_ops_filter[] __read_mostly = {
static int __net_init frame_filter_net_init(struct net *net)
{
net->xt.frame_filter = ebt_register_table(net, &frame_filter);
- if (IS_ERR(net->xt.frame_filter))
- return PTR_ERR(net->xt.frame_filter);
- return 0;
+ return PTR_RET(net->xt.frame_filter);
}
static void __net_exit frame_filter_net_exit(struct net *net)
diff --git a/net/bridge/netfilter/ebtable_nat.c b/net/bridge/netfilter/ebtable_nat.c
index 6dc2f87..10871bc 100644
--- a/net/bridge/netfilter/ebtable_nat.c
+++ b/net/bridge/netfilter/ebtable_nat.c
@@ -100,9 +100,7 @@ static struct nf_hook_ops ebt_ops_nat[] __read_mostly = {
static int __net_init frame_nat_net_init(struct net *net)
{
net->xt.frame_nat = ebt_register_table(net, &frame_nat);
- if (IS_ERR(net->xt.frame_nat))
- return PTR_ERR(net->xt.frame_nat);
- return 0;
+ return PTR_RET(net->xt.frame_nat);
}
static void __net_exit frame_nat_net_exit(struct net *net)
diff --git a/net/ipv4/netfilter/iptable_filter.c b/net/ipv4/netfilter/iptable_filter.c
index 851acec8..d20cc37 100644
--- a/net/ipv4/netfilter/iptable_filter.c
+++ b/net/ipv4/netfilter/iptable_filter.c
@@ -69,9 +69,7 @@ static int __net_init iptable_filter_net_init(struct net *net)
net->ipv4.iptable_filter =
ipt_register_table(net, &packet_filter, repl);
kfree(repl);
- if (IS_ERR(net->ipv4.iptable_filter))
- return PTR_ERR(net->ipv4.iptable_filter);
- return 0;
+ return PTR_RET(net->ipv4.iptable_filter);
}
static void __net_exit iptable_filter_net_exit(struct net *net)
diff --git a/net/ipv4/netfilter/iptable_mangle.c b/net/ipv4/netfilter/iptable_mangle.c
index aef5d1f..f38b942 100644
--- a/net/ipv4/netfilter/iptable_mangle.c
+++ b/net/ipv4/netfilter/iptable_mangle.c
@@ -104,9 +104,7 @@ static int __net_init iptable_mangle_net_init(struct net *net)
net->ipv4.iptable_mangle =
ipt_register_table(net, &packet_mangler, repl);
kfree(repl);
- if (IS_ERR(net->ipv4.iptable_mangle))
- return PTR_ERR(net->ipv4.iptable_mangle);
- return 0;
+ return PTR_RET(net->ipv4.iptable_mangle);
}
static void __net_exit iptable_mangle_net_exit(struct net *net)
diff --git a/net/ipv4/netfilter/iptable_raw.c b/net/ipv4/netfilter/iptable_raw.c
index 07fb710..b21e219 100644
--- a/net/ipv4/netfilter/iptable_raw.c
+++ b/net/ipv4/netfilter/iptable_raw.c
@@ -48,9 +48,7 @@ static int __net_init iptable_raw_net_init(struct net *net)
net->ipv4.iptable_raw =
ipt_register_table(net, &packet_raw, repl);
kfree(repl);
- if (IS_ERR(net->ipv4.iptable_raw))
- return PTR_ERR(net->ipv4.iptable_raw);
- return 0;
+ return PTR_RET(net->ipv4.iptable_raw);
}
static void __net_exit iptable_raw_net_exit(struct net *net)
diff --git a/net/ipv4/netfilter/iptable_security.c b/net/ipv4/netfilter/iptable_security.c
index be45bdc..b283d8e 100644
--- a/net/ipv4/netfilter/iptable_security.c
+++ b/net/ipv4/netfilter/iptable_security.c
@@ -66,10 +66,7 @@ static int __net_init iptable_security_net_init(struct net *net)
net->ipv4.iptable_security =
ipt_register_table(net, &security_table, repl);
kfree(repl);
- if (IS_ERR(net->ipv4.iptable_security))
- return PTR_ERR(net->ipv4.iptable_security);
-
- return 0;
+ return PTR_RET(net->ipv4.iptable_security);
}
static void __net_exit iptable_security_net_exit(struct net *net)
diff --git a/net/ipv6/netfilter/ip6table_filter.c b/net/ipv6/netfilter/ip6table_filter.c
index 325e59a..beb5777 100644
--- a/net/ipv6/netfilter/ip6table_filter.c
+++ b/net/ipv6/netfilter/ip6table_filter.c
@@ -61,9 +61,7 @@ static int __net_init ip6table_filter_net_init(struct net *net)
net->ipv6.ip6table_filter =
ip6t_register_table(net, &packet_filter, repl);
kfree(repl);
- if (IS_ERR(net->ipv6.ip6table_filter))
- return PTR_ERR(net->ipv6.ip6table_filter);
- return 0;
+ return PTR_RET(net->ipv6.ip6table_filter);
}
static void __net_exit ip6table_filter_net_exit(struct net *net)
diff --git a/net/ipv6/netfilter/ip6table_mangle.c b/net/ipv6/netfilter/ip6table_mangle.c
index 4d78240..7431121 100644
--- a/net/ipv6/netfilter/ip6table_mangle.c
+++ b/net/ipv6/netfilter/ip6table_mangle.c
@@ -97,9 +97,7 @@ static int __net_init ip6table_mangle_net_init(struct net *net)
net->ipv6.ip6table_mangle =
ip6t_register_table(net, &packet_mangler, repl);
kfree(repl);
- if (IS_ERR(net->ipv6.ip6table_mangle))
- return PTR_ERR(net->ipv6.ip6table_mangle);
- return 0;
+ return PTR_RET(net->ipv6.ip6table_mangle);
}
static void __net_exit ip6table_mangle_net_exit(struct net *net)
diff --git a/net/ipv6/netfilter/ip6table_raw.c b/net/ipv6/netfilter/ip6table_raw.c
index 5b9926a..60d1bdd 100644
--- a/net/ipv6/netfilter/ip6table_raw.c
+++ b/net/ipv6/netfilter/ip6table_raw.c
@@ -40,9 +40,7 @@ static int __net_init ip6table_raw_net_init(struct net *net)
net->ipv6.ip6table_raw =
ip6t_register_table(net, &packet_raw, repl);
kfree(repl);
- if (IS_ERR(net->ipv6.ip6table_raw))
- return PTR_ERR(net->ipv6.ip6table_raw);
- return 0;
+ return PTR_RET(net->ipv6.ip6table_raw);
}
static void __net_exit ip6table_raw_net_exit(struct net *net)
diff --git a/net/ipv6/netfilter/ip6table_security.c b/net/ipv6/netfilter/ip6table_security.c
index 91aa2b4..db15535 100644
--- a/net/ipv6/netfilter/ip6table_security.c
+++ b/net/ipv6/netfilter/ip6table_security.c
@@ -58,10 +58,7 @@ static int __net_init ip6table_security_net_init(struct net *net)
net->ipv6.ip6table_security =
ip6t_register_table(net, &security_table, repl);
kfree(repl);
- if (IS_ERR(net->ipv6.ip6table_security))
- return PTR_ERR(net->ipv6.ip6table_security);
-
- return 0;
+ return PTR_RET(net->ipv6.ip6table_security);
}
static void __net_exit ip6table_security_net_exit(struct net *net)
--
1.7.10.4
^ permalink raw reply related
* [PATCH 05/10] ipvs: add pmtu_disc option to disable IP DF for TUN packets
From: pablo @ 2012-08-22 23:38 UTC (permalink / raw)
To: netfilter-devel; +Cc: davem, netdev
In-Reply-To: <1345678726-3109-1-git-send-email-pablo@netfilter.org>
From: Julian Anastasov <ja@ssi.bg>
Disabling PMTU discovery can increase the output packet
rate but some users have enough resources and prefer to fragment
than to drop traffic. By default, we copy the DF bit but if
pmtu_disc is disabled we do not send FRAG_NEEDED messages anymore.
Signed-off-by: Julian Anastasov <ja@ssi.bg>
Signed-off-by: Simon Horman <horms@verge.net.au>
---
include/net/ip_vs.h | 11 +++++++++++
net/netfilter/ipvs/ip_vs_ctl.c | 8 ++++++++
net/netfilter/ipvs/ip_vs_xmit.c | 6 +++---
3 files changed, 22 insertions(+), 3 deletions(-)
diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h
index 4b8f18f..ee75ccd 100644
--- a/include/net/ip_vs.h
+++ b/include/net/ip_vs.h
@@ -888,6 +888,7 @@ struct netns_ipvs {
unsigned int sysctl_sync_refresh_period;
int sysctl_sync_retries;
int sysctl_nat_icmp_send;
+ int sysctl_pmtu_disc;
/* ip_vs_lblc */
int sysctl_lblc_expiration;
@@ -974,6 +975,11 @@ static inline int sysctl_sync_sock_size(struct netns_ipvs *ipvs)
return ipvs->sysctl_sync_sock_size;
}
+static inline int sysctl_pmtu_disc(struct netns_ipvs *ipvs)
+{
+ return ipvs->sysctl_pmtu_disc;
+}
+
#else
static inline int sysctl_sync_threshold(struct netns_ipvs *ipvs)
@@ -1016,6 +1022,11 @@ static inline int sysctl_sync_sock_size(struct netns_ipvs *ipvs)
return 0;
}
+static inline int sysctl_pmtu_disc(struct netns_ipvs *ipvs)
+{
+ return 1;
+}
+
#endif
/*
diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c
index d6d5cca..03d3fc6 100644
--- a/net/netfilter/ipvs/ip_vs_ctl.c
+++ b/net/netfilter/ipvs/ip_vs_ctl.c
@@ -1801,6 +1801,12 @@ static struct ctl_table vs_vars[] = {
.mode = 0644,
.proc_handler = proc_dointvec,
},
+ {
+ .procname = "pmtu_disc",
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = proc_dointvec,
+ },
#ifdef CONFIG_IP_VS_DEBUG
{
.procname = "debug_level",
@@ -3726,6 +3732,8 @@ static int __net_init ip_vs_control_net_init_sysctl(struct net *net)
ipvs->sysctl_sync_retries = clamp_t(int, DEFAULT_SYNC_RETRIES, 0, 3);
tbl[idx++].data = &ipvs->sysctl_sync_retries;
tbl[idx++].data = &ipvs->sysctl_nat_icmp_send;
+ ipvs->sysctl_pmtu_disc = 1;
+ tbl[idx++].data = &ipvs->sysctl_pmtu_disc;
ipvs->sysctl_hdr = register_net_sysctl(net, "net/ipv4/vs", tbl);
diff --git a/net/netfilter/ipvs/ip_vs_xmit.c b/net/netfilter/ipvs/ip_vs_xmit.c
index c2275ba..543a554 100644
--- a/net/netfilter/ipvs/ip_vs_xmit.c
+++ b/net/netfilter/ipvs/ip_vs_xmit.c
@@ -795,6 +795,7 @@ int
ip_vs_tunnel_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
struct ip_vs_protocol *pp)
{
+ struct netns_ipvs *ipvs = net_ipvs(skb_net(skb));
struct rtable *rt; /* Route to the other host */
__be32 saddr; /* Source for tunnel */
struct net_device *tdev; /* Device to other host */
@@ -830,10 +831,9 @@ ip_vs_tunnel_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
skb_dst(skb)->ops->update_pmtu(skb_dst(skb), NULL, skb, mtu);
/* Copy DF, reset fragment offset and MF */
- df = old_iph->frag_off & htons(IP_DF);
+ df = sysctl_pmtu_disc(ipvs) ? old_iph->frag_off & htons(IP_DF) : 0;
- if ((old_iph->frag_off & htons(IP_DF) &&
- mtu < ntohs(old_iph->tot_len) && !skb_is_gso(skb))) {
+ if (df && mtu < ntohs(old_iph->tot_len) && !skb_is_gso(skb)) {
icmp_send(skb, ICMP_DEST_UNREACH,ICMP_FRAG_NEEDED, htonl(mtu));
IP_VS_DBG_RL("%s(): frag needed\n", __func__);
goto tx_error_put;
--
1.7.10.4
^ permalink raw reply related
* [PATCH 04/10] ipvs: implement passive PMTUD for IPIP packets
From: pablo @ 2012-08-22 23:38 UTC (permalink / raw)
To: netfilter-devel; +Cc: davem, netdev
In-Reply-To: <1345678726-3109-1-git-send-email-pablo@netfilter.org>
From: Julian Anastasov <ja@ssi.bg>
IPVS is missing the logic to update PMTU in routing
for its IPIP packets. We monitor the dst_mtu and can return
FRAG_NEEDED messages but if the tunneled packets get ICMP
error we can not rely on other traffic to save the lowest
MTU.
The following patch adds ICMP handling for IPIP
packets in incoming direction, from some remote host to
our local IP used as saddr in the outer header. By this
way we can forward any related ICMP traffic if it is for IPVS
TUN connection. For the special case of PMTUD we update the
routing and if client requested DF we can forward the
error.
To properly update the routing we have to bind
the cached route (dest->dst_cache) to the selected saddr
because ipv4_update_pmtu uses saddr for dst lookup.
Add IP_VS_RT_MODE_CONNECT flag to force such binding with
second route.
Update ip_vs_tunnel_xmit to provide IP_VS_RT_MODE_CONNECT
and change the code to copy DF. For now we prefer not to
force PMTU discovery (outer DF=1) because we don't have
configuration option to enable or disable PMTUD. As we
do not keep any packets to resend, we prefer not to
play games with packets without DF bit because the sender
is not informed when they are rejected.
Also, change ops->update_pmtu to be called only
for local clients because there is no point to update
MTU for input routes, in our case skb->dst->dev is lo.
It seems the code is copied from ipip.c where the skb
dst points to tunnel device.
Signed-off-by: Julian Anastasov <ja@ssi.bg>
Signed-off-by: Simon Horman <horms@verge.net.au>
---
net/netfilter/ipvs/ip_vs_core.c | 76 +++++++++++++++++++++++++++++++++++--
net/netfilter/ipvs/ip_vs_xmit.c | 79 +++++++++++++++++++++++++++------------
2 files changed, 128 insertions(+), 27 deletions(-)
diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c
index b54ecce..58918e2 100644
--- a/net/netfilter/ipvs/ip_vs_core.c
+++ b/net/netfilter/ipvs/ip_vs_core.c
@@ -1303,7 +1303,8 @@ ip_vs_in_icmp(struct sk_buff *skb, int *related, unsigned int hooknum)
struct ip_vs_conn *cp;
struct ip_vs_protocol *pp;
struct ip_vs_proto_data *pd;
- unsigned int offset, ihl, verdict;
+ unsigned int offset, offset2, ihl, verdict;
+ bool ipip;
*related = 1;
@@ -1345,6 +1346,21 @@ ip_vs_in_icmp(struct sk_buff *skb, int *related, unsigned int hooknum)
net = skb_net(skb);
+ /* Special case for errors for IPIP packets */
+ ipip = false;
+ if (cih->protocol == IPPROTO_IPIP) {
+ if (unlikely(cih->frag_off & htons(IP_OFFSET)))
+ return NF_ACCEPT;
+ /* Error for our IPIP must arrive at LOCAL_IN */
+ if (!(skb_rtable(skb)->rt_flags & RTCF_LOCAL))
+ return NF_ACCEPT;
+ offset += cih->ihl * 4;
+ cih = skb_header_pointer(skb, offset, sizeof(_ciph), &_ciph);
+ if (cih == NULL)
+ return NF_ACCEPT; /* The packet looks wrong, ignore */
+ ipip = true;
+ }
+
pd = ip_vs_proto_data_get(net, cih->protocol);
if (!pd)
return NF_ACCEPT;
@@ -1358,11 +1374,14 @@ ip_vs_in_icmp(struct sk_buff *skb, int *related, unsigned int hooknum)
IP_VS_DBG_PKT(11, AF_INET, pp, skb, offset,
"Checking incoming ICMP for");
+ offset2 = offset;
offset += cih->ihl * 4;
ip_vs_fill_iphdr(AF_INET, cih, &ciph);
- /* The embedded headers contain source and dest in reverse order */
- cp = pp->conn_in_get(AF_INET, skb, &ciph, offset, 1);
+ /* The embedded headers contain source and dest in reverse order.
+ * For IPIP this is error for request, not for reply.
+ */
+ cp = pp->conn_in_get(AF_INET, skb, &ciph, offset, ipip ? 0 : 1);
if (!cp)
return NF_ACCEPT;
@@ -1376,6 +1395,57 @@ ip_vs_in_icmp(struct sk_buff *skb, int *related, unsigned int hooknum)
goto out;
}
+ if (ipip) {
+ __be32 info = ic->un.gateway;
+
+ /* Update the MTU */
+ if (ic->type == ICMP_DEST_UNREACH &&
+ ic->code == ICMP_FRAG_NEEDED) {
+ struct ip_vs_dest *dest = cp->dest;
+ u32 mtu = ntohs(ic->un.frag.mtu);
+
+ /* Strip outer IP and ICMP, go to IPIP header */
+ __skb_pull(skb, ihl + sizeof(_icmph));
+ offset2 -= ihl + sizeof(_icmph);
+ skb_reset_network_header(skb);
+ IP_VS_DBG(12, "ICMP for IPIP %pI4->%pI4: mtu=%u\n",
+ &ip_hdr(skb)->saddr, &ip_hdr(skb)->daddr, mtu);
+ rcu_read_lock();
+ ipv4_update_pmtu(skb, dev_net(skb->dev),
+ mtu, 0, 0, 0, 0);
+ rcu_read_unlock();
+ /* Client uses PMTUD? */
+ if (!(cih->frag_off & htons(IP_DF)))
+ goto ignore_ipip;
+ /* Prefer the resulting PMTU */
+ if (dest) {
+ spin_lock(&dest->dst_lock);
+ if (dest->dst_cache)
+ mtu = dst_mtu(dest->dst_cache);
+ spin_unlock(&dest->dst_lock);
+ }
+ if (mtu > 68 + sizeof(struct iphdr))
+ mtu -= sizeof(struct iphdr);
+ info = htonl(mtu);
+ }
+ /* Strip outer IP, ICMP and IPIP, go to IP header of
+ * original request.
+ */
+ __skb_pull(skb, offset2);
+ skb_reset_network_header(skb);
+ IP_VS_DBG(12, "Sending ICMP for %pI4->%pI4: t=%u, c=%u, i=%u\n",
+ &ip_hdr(skb)->saddr, &ip_hdr(skb)->daddr,
+ ic->type, ic->code, ntohl(info));
+ icmp_send(skb, ic->type, ic->code, info);
+ /* ICMP can be shorter but anyways, account it */
+ ip_vs_out_stats(cp, skb);
+
+ignore_ipip:
+ consume_skb(skb);
+ verdict = NF_STOLEN;
+ goto out;
+ }
+
/* do the statistics and put it back */
ip_vs_in_stats(cp, skb);
if (IPPROTO_TCP == cih->protocol || IPPROTO_UDP == cih->protocol)
diff --git a/net/netfilter/ipvs/ip_vs_xmit.c b/net/netfilter/ipvs/ip_vs_xmit.c
index 65b616a..c2275ba 100644
--- a/net/netfilter/ipvs/ip_vs_xmit.c
+++ b/net/netfilter/ipvs/ip_vs_xmit.c
@@ -49,6 +49,7 @@ enum {
IP_VS_RT_MODE_RDR = 4, /* Allow redirect from remote daddr to
* local
*/
+ IP_VS_RT_MODE_CONNECT = 8, /* Always bind route to saddr */
};
/*
@@ -84,6 +85,42 @@ __ip_vs_dst_check(struct ip_vs_dest *dest, u32 rtos)
return dst;
}
+/* Get route to daddr, update *saddr, optionally bind route to saddr */
+static struct rtable *do_output_route4(struct net *net, __be32 daddr,
+ u32 rtos, int rt_mode, __be32 *saddr)
+{
+ struct flowi4 fl4;
+ struct rtable *rt;
+ int loop = 0;
+
+ memset(&fl4, 0, sizeof(fl4));
+ fl4.daddr = daddr;
+ fl4.saddr = (rt_mode & IP_VS_RT_MODE_CONNECT) ? *saddr : 0;
+ fl4.flowi4_tos = rtos;
+
+retry:
+ rt = ip_route_output_key(net, &fl4);
+ if (IS_ERR(rt)) {
+ /* Invalid saddr ? */
+ if (PTR_ERR(rt) == -EINVAL && *saddr &&
+ rt_mode & IP_VS_RT_MODE_CONNECT && !loop) {
+ *saddr = 0;
+ flowi4_update_output(&fl4, 0, rtos, daddr, 0);
+ goto retry;
+ }
+ IP_VS_DBG_RL("ip_route_output error, dest: %pI4\n", &daddr);
+ return NULL;
+ } else if (!*saddr && rt_mode & IP_VS_RT_MODE_CONNECT && fl4.saddr) {
+ ip_rt_put(rt);
+ *saddr = fl4.saddr;
+ flowi4_update_output(&fl4, 0, rtos, daddr, fl4.saddr);
+ loop++;
+ goto retry;
+ }
+ *saddr = fl4.saddr;
+ return rt;
+}
+
/* Get route to destination or remote server */
static struct rtable *
__ip_vs_get_out_rt(struct sk_buff *skb, struct ip_vs_dest *dest,
@@ -98,20 +135,13 @@ __ip_vs_get_out_rt(struct sk_buff *skb, struct ip_vs_dest *dest,
spin_lock(&dest->dst_lock);
if (!(rt = (struct rtable *)
__ip_vs_dst_check(dest, rtos))) {
- struct flowi4 fl4;
-
- memset(&fl4, 0, sizeof(fl4));
- fl4.daddr = dest->addr.ip;
- fl4.flowi4_tos = rtos;
- rt = ip_route_output_key(net, &fl4);
- if (IS_ERR(rt)) {
+ rt = do_output_route4(net, dest->addr.ip, rtos,
+ rt_mode, &dest->dst_saddr.ip);
+ if (!rt) {
spin_unlock(&dest->dst_lock);
- IP_VS_DBG_RL("ip_route_output error, dest: %pI4\n",
- &dest->addr.ip);
return NULL;
}
__ip_vs_dst_set(dest, rtos, dst_clone(&rt->dst), 0);
- dest->dst_saddr.ip = fl4.saddr;
IP_VS_DBG(10, "new dst %pI4, src %pI4, refcnt=%d, "
"rtos=%X\n",
&dest->addr.ip, &dest->dst_saddr.ip,
@@ -122,19 +152,17 @@ __ip_vs_get_out_rt(struct sk_buff *skb, struct ip_vs_dest *dest,
*ret_saddr = dest->dst_saddr.ip;
spin_unlock(&dest->dst_lock);
} else {
- struct flowi4 fl4;
+ __be32 saddr = htonl(INADDR_ANY);
- memset(&fl4, 0, sizeof(fl4));
- fl4.daddr = daddr;
- fl4.flowi4_tos = rtos;
- rt = ip_route_output_key(net, &fl4);
- if (IS_ERR(rt)) {
- IP_VS_DBG_RL("ip_route_output error, dest: %pI4\n",
- &daddr);
+ /* For such unconfigured boxes avoid many route lookups
+ * for performance reasons because we do not remember saddr
+ */
+ rt_mode &= ~IP_VS_RT_MODE_CONNECT;
+ rt = do_output_route4(net, daddr, rtos, rt_mode, &saddr);
+ if (!rt)
return NULL;
- }
if (ret_saddr)
- *ret_saddr = fl4.saddr;
+ *ret_saddr = saddr;
}
local = rt->rt_flags & RTCF_LOCAL;
@@ -331,6 +359,7 @@ ip_vs_dst_reset(struct ip_vs_dest *dest)
old_dst = dest->dst_cache;
dest->dst_cache = NULL;
dst_release(old_dst);
+ dest->dst_saddr.ip = 0;
}
#define IP_VS_XMIT_TUNNEL(skb, cp) \
@@ -771,7 +800,7 @@ ip_vs_tunnel_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
struct net_device *tdev; /* Device to other host */
struct iphdr *old_iph = ip_hdr(skb);
u8 tos = old_iph->tos;
- __be16 df = old_iph->frag_off;
+ __be16 df;
struct iphdr *iph; /* Our new IP header */
unsigned int max_headroom; /* The extra header space needed */
int mtu;
@@ -781,7 +810,8 @@ ip_vs_tunnel_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
if (!(rt = __ip_vs_get_out_rt(skb, cp->dest, cp->daddr.ip,
RT_TOS(tos), IP_VS_RT_MODE_LOCAL |
- IP_VS_RT_MODE_NON_LOCAL,
+ IP_VS_RT_MODE_NON_LOCAL |
+ IP_VS_RT_MODE_CONNECT,
&saddr)))
goto tx_error_icmp;
if (rt->rt_flags & RTCF_LOCAL) {
@@ -796,10 +826,11 @@ ip_vs_tunnel_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
IP_VS_DBG_RL("%s(): mtu less than 68\n", __func__);
goto tx_error_put;
}
- if (skb_dst(skb))
+ if (rt_is_output_route(skb_rtable(skb)))
skb_dst(skb)->ops->update_pmtu(skb_dst(skb), NULL, skb, mtu);
- df |= (old_iph->frag_off & htons(IP_DF));
+ /* Copy DF, reset fragment offset and MF */
+ df = old_iph->frag_off & htons(IP_DF);
if ((old_iph->frag_off & htons(IP_DF) &&
mtu < ntohs(old_iph->tot_len) && !skb_is_gso(skb))) {
--
1.7.10.4
^ permalink raw reply related
* [PATCH 03/10] ipvs: fixed sparse warning
From: pablo @ 2012-08-22 23:38 UTC (permalink / raw)
To: netfilter-devel; +Cc: davem, netdev
In-Reply-To: <1345678726-3109-1-git-send-email-pablo@netfilter.org>
From: Claudiu Ghioc <claudiughioc@gmail.com>
Removed the following sparse warnings, wether CONFIG_SYSCTL
is defined or not:
* warning: symbol 'ip_vs_control_net_init_sysctl' was not
declared. Should it be static?
* warning: symbol 'ip_vs_control_net_cleanup_sysctl' was
not declared. Should it be static?
Signed-off-by: Claudiu Ghioc <claudiu.ghioc@gmail.com>
Signed-off-by: Simon Horman <horms@verge.net.au>
---
net/netfilter/ipvs/ip_vs_ctl.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c
index 84444dd..d6d5cca 100644
--- a/net/netfilter/ipvs/ip_vs_ctl.c
+++ b/net/netfilter/ipvs/ip_vs_ctl.c
@@ -3675,7 +3675,7 @@ static void ip_vs_genl_unregister(void)
* per netns intit/exit func.
*/
#ifdef CONFIG_SYSCTL
-int __net_init ip_vs_control_net_init_sysctl(struct net *net)
+static int __net_init ip_vs_control_net_init_sysctl(struct net *net)
{
int idx;
struct netns_ipvs *ipvs = net_ipvs(net);
@@ -3743,7 +3743,7 @@ int __net_init ip_vs_control_net_init_sysctl(struct net *net)
return 0;
}
-void __net_exit ip_vs_control_net_cleanup_sysctl(struct net *net)
+static void __net_exit ip_vs_control_net_cleanup_sysctl(struct net *net)
{
struct netns_ipvs *ipvs = net_ipvs(net);
@@ -3754,8 +3754,8 @@ void __net_exit ip_vs_control_net_cleanup_sysctl(struct net *net)
#else
-int __net_init ip_vs_control_net_init_sysctl(struct net *net) { return 0; }
-void __net_exit ip_vs_control_net_cleanup_sysctl(struct net *net) { }
+static int __net_init ip_vs_control_net_init_sysctl(struct net *net) { return 0; }
+static void __net_exit ip_vs_control_net_cleanup_sysctl(struct net *net) { }
#endif
--
1.7.10.4
^ permalink raw reply related
* [PATCH 02/10] ipvs: generalize app registration in netns
From: pablo @ 2012-08-22 23:38 UTC (permalink / raw)
To: netfilter-devel; +Cc: davem, netdev
In-Reply-To: <1345678726-3109-1-git-send-email-pablo@netfilter.org>
From: Julian Anastasov <ja@ssi.bg>
Get rid of the ftp_app pointer and allow applications
to be registered without adding fields in the netns_ipvs structure.
v2: fix coding style as suggested by Pablo Neira Ayuso <pablo@netfilter.org>
Signed-off-by: Julian Anastasov <ja@ssi.bg>
Signed-off-by: Simon Horman <horms@verge.net.au>
---
include/net/ip_vs.h | 5 ++--
net/netfilter/ipvs/ip_vs_app.c | 58 +++++++++++++++++++++++++++++-----------
net/netfilter/ipvs/ip_vs_ftp.c | 21 ++++-----------
3 files changed, 49 insertions(+), 35 deletions(-)
diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h
index 95374d1..4b8f18f 100644
--- a/include/net/ip_vs.h
+++ b/include/net/ip_vs.h
@@ -808,8 +808,6 @@ struct netns_ipvs {
struct list_head rs_table[IP_VS_RTAB_SIZE];
/* ip_vs_app */
struct list_head app_list;
- /* ip_vs_ftp */
- struct ip_vs_app *ftp_app;
/* ip_vs_proto */
#define IP_VS_PROTO_TAB_SIZE 32 /* must be power of 2 */
struct ip_vs_proto_data *proto_data_table[IP_VS_PROTO_TAB_SIZE];
@@ -1179,7 +1177,8 @@ extern void ip_vs_service_net_cleanup(struct net *net);
* (from ip_vs_app.c)
*/
#define IP_VS_APP_MAX_PORTS 8
-extern int register_ip_vs_app(struct net *net, struct ip_vs_app *app);
+extern struct ip_vs_app *register_ip_vs_app(struct net *net,
+ struct ip_vs_app *app);
extern void unregister_ip_vs_app(struct net *net, struct ip_vs_app *app);
extern int ip_vs_bind_app(struct ip_vs_conn *cp, struct ip_vs_protocol *pp);
extern void ip_vs_unbind_app(struct ip_vs_conn *cp);
diff --git a/net/netfilter/ipvs/ip_vs_app.c b/net/netfilter/ipvs/ip_vs_app.c
index 64f9e8f..9713e6e 100644
--- a/net/netfilter/ipvs/ip_vs_app.c
+++ b/net/netfilter/ipvs/ip_vs_app.c
@@ -180,22 +180,38 @@ register_ip_vs_app_inc(struct net *net, struct ip_vs_app *app, __u16 proto,
}
-/*
- * ip_vs_app registration routine
- */
-int register_ip_vs_app(struct net *net, struct ip_vs_app *app)
+/* Register application for netns */
+struct ip_vs_app *register_ip_vs_app(struct net *net, struct ip_vs_app *app)
{
struct netns_ipvs *ipvs = net_ipvs(net);
- /* increase the module use count */
- ip_vs_use_count_inc();
+ struct ip_vs_app *a;
+ int err = 0;
+
+ if (!ipvs)
+ return ERR_PTR(-ENOENT);
mutex_lock(&__ip_vs_app_mutex);
- list_add(&app->a_list, &ipvs->app_list);
+ list_for_each_entry(a, &ipvs->app_list, a_list) {
+ if (!strcmp(app->name, a->name)) {
+ err = -EEXIST;
+ goto out_unlock;
+ }
+ }
+ a = kmemdup(app, sizeof(*app), GFP_KERNEL);
+ if (!a) {
+ err = -ENOMEM;
+ goto out_unlock;
+ }
+ INIT_LIST_HEAD(&a->incs_list);
+ list_add(&a->a_list, &ipvs->app_list);
+ /* increase the module use count */
+ ip_vs_use_count_inc();
+out_unlock:
mutex_unlock(&__ip_vs_app_mutex);
- return 0;
+ return err ? ERR_PTR(err) : a;
}
@@ -205,20 +221,29 @@ int register_ip_vs_app(struct net *net, struct ip_vs_app *app)
*/
void unregister_ip_vs_app(struct net *net, struct ip_vs_app *app)
{
- struct ip_vs_app *inc, *nxt;
+ struct netns_ipvs *ipvs = net_ipvs(net);
+ struct ip_vs_app *a, *anxt, *inc, *nxt;
+
+ if (!ipvs)
+ return;
mutex_lock(&__ip_vs_app_mutex);
- list_for_each_entry_safe(inc, nxt, &app->incs_list, a_list) {
- ip_vs_app_inc_release(net, inc);
- }
+ list_for_each_entry_safe(a, anxt, &ipvs->app_list, a_list) {
+ if (app && strcmp(app->name, a->name))
+ continue;
+ list_for_each_entry_safe(inc, nxt, &a->incs_list, a_list) {
+ ip_vs_app_inc_release(net, inc);
+ }
- list_del(&app->a_list);
+ list_del(&a->a_list);
+ kfree(a);
- mutex_unlock(&__ip_vs_app_mutex);
+ /* decrease the module use count */
+ ip_vs_use_count_dec();
+ }
- /* decrease the module use count */
- ip_vs_use_count_dec();
+ mutex_unlock(&__ip_vs_app_mutex);
}
@@ -586,5 +611,6 @@ int __net_init ip_vs_app_net_init(struct net *net)
void __net_exit ip_vs_app_net_cleanup(struct net *net)
{
+ unregister_ip_vs_app(net, NULL /* all */);
proc_net_remove(net, "ip_vs_app");
}
diff --git a/net/netfilter/ipvs/ip_vs_ftp.c b/net/netfilter/ipvs/ip_vs_ftp.c
index b20b29c..ad70b7e 100644
--- a/net/netfilter/ipvs/ip_vs_ftp.c
+++ b/net/netfilter/ipvs/ip_vs_ftp.c
@@ -441,16 +441,10 @@ static int __net_init __ip_vs_ftp_init(struct net *net)
if (!ipvs)
return -ENOENT;
- app = kmemdup(&ip_vs_ftp, sizeof(struct ip_vs_app), GFP_KERNEL);
- if (!app)
- return -ENOMEM;
- INIT_LIST_HEAD(&app->a_list);
- INIT_LIST_HEAD(&app->incs_list);
- ipvs->ftp_app = app;
- ret = register_ip_vs_app(net, app);
- if (ret)
- goto err_exit;
+ app = register_ip_vs_app(net, &ip_vs_ftp);
+ if (IS_ERR(app))
+ return PTR_ERR(app);
for (i = 0; i < ports_count; i++) {
if (!ports[i])
@@ -464,9 +458,7 @@ static int __net_init __ip_vs_ftp_init(struct net *net)
return 0;
err_unreg:
- unregister_ip_vs_app(net, app);
-err_exit:
- kfree(ipvs->ftp_app);
+ unregister_ip_vs_app(net, &ip_vs_ftp);
return ret;
}
/*
@@ -474,10 +466,7 @@ err_exit:
*/
static void __ip_vs_ftp_exit(struct net *net)
{
- struct netns_ipvs *ipvs = net_ipvs(net);
-
- unregister_ip_vs_app(net, ipvs->ftp_app);
- kfree(ipvs->ftp_app);
+ unregister_ip_vs_app(net, &ip_vs_ftp);
}
static struct pernet_operations ip_vs_ftp_ops = {
--
1.7.10.4
^ permalink raw reply related
* [PATCH 01/10] ipvs: ip_vs_ftp depends on nf_conntrack_ftp helper
From: pablo @ 2012-08-22 23:38 UTC (permalink / raw)
To: netfilter-devel; +Cc: davem, netdev
In-Reply-To: <1345678726-3109-1-git-send-email-pablo@netfilter.org>
From: Julian Anastasov <ja@ssi.bg>
The FTP application indirectly depends on the
nf_conntrack_ftp helper for proper NAT support. If the
module is not loaded, IPVS can resize the packets for the
command connection, eg. PASV response but the SEQ adjustment
logic in ipv4_confirm is not called without helper.
Signed-off-by: Julian Anastasov <ja@ssi.bg>
Signed-off-by: Simon Horman <horms@verge.net.au>
---
net/netfilter/ipvs/Kconfig | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/net/netfilter/ipvs/Kconfig b/net/netfilter/ipvs/Kconfig
index f987138..8b2cffd 100644
--- a/net/netfilter/ipvs/Kconfig
+++ b/net/netfilter/ipvs/Kconfig
@@ -250,7 +250,8 @@ comment 'IPVS application helper'
config IP_VS_FTP
tristate "FTP protocol helper"
- depends on IP_VS_PROTO_TCP && NF_CONNTRACK && NF_NAT
+ depends on IP_VS_PROTO_TCP && NF_CONNTRACK && NF_NAT && \
+ NF_CONNTRACK_FTP
select IP_VS_NFCT
---help---
FTP is a protocol that transfers IP address and/or port number in
--
1.7.10.4
^ permalink raw reply related
* [PATCH 00/10] netfilter updates for net-next (batch 1)
From: pablo @ 2012-08-22 23:38 UTC (permalink / raw)
To: netfilter-devel; +Cc: davem, netdev
From: Pablo Neira Ayuso <pablo@netfilter.org>
Hi David,
This is the first batch of Netfilter and IPVS updates for your
net-next tree. Mostly cleanups for the Netfilter side. They are:
* Remove unnecessary RTNL locking now that we have support
for namespace in nf_conntrack, from Patrick McHardy.
* Cleanup to eliminate unnecessary goto in the initialization
path of several Netfilter tables, from Jean Sacren.
* Another cleanup from Wu Fengguang, this time to PTR_RET instead
of if IS_ERR then return PTR_ERR.
* Use list_for_each_entry_continue_rcu in nf_iterate, from
Michael Wang.
* Add pmtu_disc sysctl option to disable PMTU in their tunneling
transmitter, from Julian Anastasov.
* Generalize application protocol registration in IPVS and modify
IPVS FTP helper to use it, from Julian Anastasov.
* update Kconfig. The IPVS FTP helper depends on the Netfilter FTP
helper for NAT support, from Julian Anastasov.
* Add logic to update PMTU for IPIP packets in IPVS, again
from Julian Anastasov.
* A couple of sparse warning fixes for IPVS and Netfilter from
Claudiu Ghioc and Patrick McHardy respectively.
Patrick's IPv6 NAT changes will follow after this batch, I need
to flush this batch first before refreshing my tree.
You can pull these changes from:
git://1984.lsi.us.es/nf-next
Thanks!
Claudiu Ghioc (1):
ipvs: fixed sparse warning
Jean Sacren (1):
netfilter: remove unnecessary goto statement for error recovery
Julian Anastasov (4):
ipvs: ip_vs_ftp depends on nf_conntrack_ftp helper
ipvs: generalize app registration in netns
ipvs: implement passive PMTUD for IPIP packets
ipvs: add pmtu_disc option to disable IP DF for TUN packets
Michael Wang (1):
netfilter: replace list_for_each_continue_rcu with new interface
Patrick McHardy (2):
netfilter: sparse endian fixes
netfilter: nf_conntrack: remove unnecessary RTNL locking
Wu Fengguang (1):
netfilter: PTR_RET can be used
include/net/ip_vs.h | 16 ++++--
net/bridge/netfilter/ebtable_filter.c | 4 +-
net/bridge/netfilter/ebtable_nat.c | 4 +-
net/ipv4/netfilter/iptable_filter.c | 10 +---
net/ipv4/netfilter/iptable_mangle.c | 10 +---
net/ipv4/netfilter/iptable_raw.c | 10 +---
net/ipv4/netfilter/iptable_security.c | 5 +-
net/ipv6/netfilter/ip6table_filter.c | 4 +-
net/ipv6/netfilter/ip6table_mangle.c | 4 +-
net/ipv6/netfilter/ip6table_raw.c | 4 +-
net/ipv6/netfilter/ip6table_security.c | 5 +-
net/netfilter/core.c | 10 ++--
net/netfilter/ipvs/Kconfig | 3 +-
net/netfilter/ipvs/ip_vs_app.c | 58 ++++++++++++++++------
net/netfilter/ipvs/ip_vs_core.c | 76 +++++++++++++++++++++++++++--
net/netfilter/ipvs/ip_vs_ctl.c | 16 ++++--
net/netfilter/ipvs/ip_vs_ftp.c | 21 ++------
net/netfilter/ipvs/ip_vs_xmit.c | 83 ++++++++++++++++++++++----------
net/netfilter/nf_conntrack_proto.c | 5 --
net/netfilter/nfnetlink_acct.c | 4 +-
net/netfilter/nfnetlink_cthelper.c | 2 +-
net/netfilter/xt_NFQUEUE.c | 8 +--
net/netfilter/xt_osf.c | 2 +-
23 files changed, 232 insertions(+), 132 deletions(-)
--
1.7.10.4
^ permalink raw reply
* Re: [PATCH 1/1] ipv4: ipmr_expire_timer causes crash when removing net namespace
From: Francesco Ruggeri @ 2012-08-22 22:56 UTC (permalink / raw)
To: Eric Dumazet; +Cc: netdev, Eric W. Biederman
In-Reply-To: <1345526991.5158.373.camel@edumazet-glaptop>
On Mon, Aug 20, 2012 at 10:29 PM, Eric Dumazet <eric.dumazet@gmail.com> wrote:
> On Mon, 2012-08-20 at 17:15 -0700, Francesco Ruggeri wrote:
>> I
>> +static void ipmr_free_table(struct mr_table *mrt)
>> +{
>> + del_timer(&mrt->ipmr_expire_timer);
>> + mroute_clean_tables(mrt);
>> + kfree(mrt);
>> +}
>
> Seems racy to me.
>
> del_timer() doesnt make sure timer is completely disabled.
>
> Probably need spin_lock_bh(&mfc_unres_lock) /
> spin_unlock_bh(&mfc_unres_lock), and maybe del_timer_sync()
>
I see your point, del_timer_sync should be used to take care of any
pending timers.
I am not sure about the need for further locking though. This function
simply replaces a direct call to kfree(mrt), so I assume by this point
today's code already makes sure no one is going to access this
structure (including to start the timer), or we have a bigger problem
than just the timer.
Maybe someone familiar with ipmr can comment.
Francesco
>
>
^ permalink raw reply
* Re: [PATCH] netdev/phy: add MDIO bus multiplexer driven by a memory-mapped FPGA
From: David Daney @ 2012-08-22 22:52 UTC (permalink / raw)
To: Timur Tabi
Cc: David Daney, devicetree-discuss@lists.ozlabs.org, Andy Fleming,
David Miller, netdev, david.daney
In-Reply-To: <50355F6D.4070002@freescale.com>
On 08/22/2012 03:38 PM, Timur Tabi wrote:
> David Daney wrote:
>
>> I wonder if *fpga is really a good name for this. It is a general
>> purpose multiplexer with a memory mapped control register. I would call
>> it something like mdio-mux-mmioreg.
>
> At one point, I thought of using mdio-mux-bitbang, but -mmioreg is better.
> Thanks.
>
>>> +- mdio-mux-device : phandle, points to the FPGA (or similar) node. This
>>> + must be a memory-mapped device with 8-bit registers.
>>
>> You shouldn't need this. Just make the multiplexer a child of FPGA node
>> to indicate where it lives.
>
> The problem is that we don't normally consider the FPGA node to be a bus,
> so its child nodes won't get probed. That's why I have this:
>
That would seem to be a mistake/error.
You should be able to arrive at any directly addressable register by
walking down the tree to the children and applying any "ranges"
properties at each node. The OF infrastructure will take care of
resolving all the addresses and you get rid of much of the code you
added to duplicate its function.
^ permalink raw reply
* Re: [PATCH 06/18] netfilter: add protocol independant NAT core
From: Jan Engelhardt @ 2012-08-22 22:48 UTC (permalink / raw)
To: Patrick McHardy; +Cc: netfilter-devel, netdev
In-Reply-To: <Pine.GSO.4.63.1208230008220.5113@stinky-local.trash.net>
On Thursday 2012-08-23 00:13, Patrick McHardy wrote:
>>> + iph = (void *)skb->data + iphdroff;
>>
>> Is trying to avoid some GNU extensions a worthwhile goal? If so,
>> iph = (struct iphdr *)(skb->data + iphdroff) should be used, like in:
>
> I don't get your point.
You are doing arithmetic with a void* pointer, which is a GNU extension.
Should we try to limit "unnecessary excess usage" of GNU features?
You could do arithmetic with the char* that skb->data is:
iph = (void *)(skb->data + iphdroff);
or, if more clarity is desired, the more verbose form
iph = (struct iphdr *)(skb->data + iphdroff);
Does this seem like something worthwhile to passively pursue?
^ permalink raw reply
* Re: [PATCH] netdev/phy: add MDIO bus multiplexer driven by a memory-mapped FPGA
From: Timur Tabi @ 2012-08-22 22:38 UTC (permalink / raw)
To: David Daney
Cc: devicetree-discuss@lists.ozlabs.org, Andy Fleming, David Miller,
netdev, david.daney
In-Reply-To: <50355C05.6000407@gmail.com>
David Daney wrote:
> I wonder if *fpga is really a good name for this. It is a general
> purpose multiplexer with a memory mapped control register. I would call
> it something like mdio-mux-mmioreg.
At one point, I thought of using mdio-mux-bitbang, but -mmioreg is better.
Thanks.
>> +- mdio-mux-device : phandle, points to the FPGA (or similar) node. This
>> + must be a memory-mapped device with 8-bit registers.
>
> You shouldn't need this. Just make the multiplexer a child of FPGA node
> to indicate where it lives.
The problem is that we don't normally consider the FPGA node to be a bus,
so its child nodes won't get probed. That's why I have this:
compatible = "mdio-mux-fpga", "mdio-mux";
^^^^^^^^
This allows me to have multiple mdio-mux parent nodes (which I do, since I
have multiple mdio bus muxes), and they all get registered and probed
properly because I also do this:
static const struct of_device_id of_device_ids[] __devinitconst = {
{
.compatible = "simple-bus"
},
{
.compatible = "fsl,srio",
},
...
{
.compatible = "mdio-mux",
},
{}
};
The .compatible = "mdio-mux" is what causes all of the mdio-mux nodes to
be registered. Therefore, it's simpler if all the mdio-mux nodes are root
nodes.
>> +
>> +- mdio-mux-register : integer, contains the offset of the register that
>> + controls the bus multiplexer.
>
> This should just be the normal "reg" properly
Ok.
>> +- mdio-mux-mask : integer, contains an 8-bit mask that specifies which
>> + bits in the register control the actual bus multiplexer. The
>> + 'reg' property of each child mdio-mux node must be constrained by
>> + this mask.
>> +
>
> "reg-mask" ??
Ok.
>
> Do you need a shift too?
The 'reg' property of the mdio bus child nodes should take the shift into
account. That's why, in the example, I have mask=0x6 and reg=0 or reg=2.
There's even code in the driver to make sure that the 'reg' values are
constrained to the mask.
--
Timur Tabi
Linux kernel developer at Freescale
^ permalink raw reply
* Re: [PATCH net-next] ipv4/netfilter: remove unnecessary goto statement for error recovery
From: Pablo Neira Ayuso @ 2012-08-22 22:33 UTC (permalink / raw)
To: Jean Sacren; +Cc: netfilter-devel, netdev
In-Reply-To: <1345425092-11905-1-git-send-email-sakiwit@gmail.com>
On Sun, Aug 19, 2012 at 07:11:32PM -0600, Jean Sacren wrote:
> Usually it's a good practice to use goto statement for error recovery
> when initializing the module. This approach could be an overkill if:
>
> 1) there is only one fail case;
> 2) success and failure use the same return statement.
>
> For a cleaner approach, remove the unnecessary goto statement and
> directly implement error recovery.
Applied, thanks Jean.
^ permalink raw reply
* Re: [PATCH 3/3] netfilter: replace list_for_each_continue_rcu with new interface
From: Pablo Neira Ayuso @ 2012-08-22 22:32 UTC (permalink / raw)
To: Michael Wang
Cc: LKML, netdev@vger.kernel.org, netfilter, coreteam,
netfilter-devel, David Miller, kaber, paulmck@linux.vnet.ibm.com
In-Reply-To: <502DC9A3.2070703@linux.vnet.ibm.com>
On Fri, Aug 17, 2012 at 12:33:39PM +0800, Michael Wang wrote:
> From: Michael Wang <wangyun@linux.vnet.ibm.com>
>
> This patch replaces list_for_each_continue_rcu() with
> list_for_each_entry_continue_rcu() to allow removing
> list_for_each_continue_rcu().
Applied, thanks.
^ permalink raw reply
* Re: [PATCH] netdev/phy: add MDIO bus multiplexer driven by a memory-mapped FPGA
From: David Daney @ 2012-08-22 22:24 UTC (permalink / raw)
To: Timur Tabi, devicetree-discuss@lists.ozlabs.org
Cc: Andy Fleming, David Miller, netdev, david.daney
In-Reply-To: <1345671954-6398-1-git-send-email-timur@freescale.com>
On 08/22/2012 02:45 PM, Timur Tabi wrote:
> An FPGA controls which sub-bus is connected to the master MDIO bus. The
> FPGA must be memory-mapped and contain only 8-bit registers (which keeps
> things simple).
>
> Tested on a Freescale P5020DS board which uses the "PIXIS" FPGA attached
> to the localbus.
>
> Signed-off-by: Timur Tabi <timur@freescale.com>
> ---
> .../devicetree/bindings/net/mdio-mux-fpga.txt | 74 ++++++++
> drivers/net/phy/Kconfig | 13 ++
> drivers/net/phy/Makefile | 1 +
> drivers/net/phy/mdio-mux-fpga.c | 186 ++++++++++++++++++++
I am fine with the general concept of the patch, so I am going to start
a Bike Shedding session with it over the names of some of the things here.
I wonder if *fpga is really a good name for this. It is a general
purpose multiplexer with a memory mapped control register. I would call
it something like mdio-mux-mmioreg.
> 4 files changed, 274 insertions(+), 0 deletions(-)
> create mode 100644 Documentation/devicetree/bindings/net/mdio-mux-fpga.txt
> create mode 100644 drivers/net/phy/mdio-mux-fpga.c
>
> diff --git a/Documentation/devicetree/bindings/net/mdio-mux-fpga.txt b/Documentation/devicetree/bindings/net/mdio-mux-fpga.txt
> new file mode 100644
> index 0000000..ef567c6
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/net/mdio-mux-fpga.txt
> @@ -0,0 +1,74 @@
> +Properties for an MDIO bus multiplexer/switch controlled by an FPGA register.
> +
> +This is a special case of a MDIO bus multiplexer. An FPGA register is used
> +to control which child bus is connected.
> +
> +Required properties in addition to the generic multiplexer properties:
> +
> +- compatible : string, must contain "mdio-mux-fpga"
> +
> +- mdio-mux-device : phandle, points to the FPGA (or similar) node. This
> + must be a memory-mapped device with 8-bit registers.
You shouldn't need this. Just make the multiplexer a child of FPGA node
to indicate where it lives.
> +
> +- mdio-mux-register : integer, contains the offset of the register that
> + controls the bus multiplexer.
This should just be the normal "reg" properly
> +
> +- mdio-mux-mask : integer, contains an 8-bit mask that specifies which
> + bits in the register control the actual bus multiplexer. The
> + 'reg' property of each child mdio-mux node must be constrained by
> + this mask.
> +
"reg-mask" ??
Do you need a shift too?
David Daney
^ permalink raw reply
* Re: [PATCH 00/18] netfilter: IPv6 NAT
From: Pablo Neira Ayuso @ 2012-08-22 22:22 UTC (permalink / raw)
To: David Miller; +Cc: kaber, netfilter-devel, netdev
In-Reply-To: <20120822.144208.2245712403707914143.davem@davemloft.net>
On Wed, Aug 22, 2012 at 02:42:08PM -0700, David Miller wrote:
> From: Patrick McHardy <kaber@trash.net>
> Date: Wed, 22 Aug 2012 23:23:53 +0200 (MEST)
>
> > The NAT patches depend on a couple of fixes in Pablo's latest
> > submission, if you could merge net.git into net-next.git, I can push
> > them to Pablo without creating conflicts. Thanks!
>
> I just did that right now, should show up on kernel.org shortly.
First, I'll pass you a Netfilter batch with 10 patches asap.
Then, I'll refresh my tree and apply Patrick's NAT patches.
^ permalink raw reply
* Re: [PATCH 00/18] netfilter: IPv6 NAT
From: Patrick McHardy @ 2012-08-22 22:21 UTC (permalink / raw)
To: David Miller; +Cc: netfilter-devel, netdev
In-Reply-To: <20120822.144208.2245712403707914143.davem@davemloft.net>
On Wed, 22 Aug 2012, David Miller wrote:
> From: Patrick McHardy <kaber@trash.net>
> Date: Wed, 22 Aug 2012 23:23:53 +0200 (MEST)
>
>> The NAT patches depend on a couple of fixes in Pablo's latest
>> submission, if you could merge net.git into net-next.git, I can push
>> them to Pablo without creating conflicts. Thanks!
>
> I just did that right now, should show up on kernel.org shortly.
Thanks Dave.
^ permalink raw reply
* Re: [PATCH 05/19] netfilter: nf_conntrack_ipv6: improve fragmentation handling
From: Patrick McHardy @ 2012-08-22 22:21 UTC (permalink / raw)
To: Jesper Dangaard Brouer; +Cc: netfilter-devel, netdev
In-Reply-To: <1345468385.3069.251.camel@localhost>
On Mon, 20 Aug 2012, Jesper Dangaard Brouer wrote:
> On Sun, 2012-08-19 at 21:44 +0200, Patrick McHardy wrote:
>
>> Could you send me your patch so I get a better picture of what you're
>> doing exactly?
>
> Okay, just posted the patchset.
>
> Specifically look at patch:
> [PATCH 3/3] ipvs: Complete IPv6 fragment handling for IPVS
>
> Where I use the hook to copy the fw mark from the reasm SKB packet to
> the SKB fragments. (Perhaps, this could be done else were in the
> netfilter framework).
Thanks, I'll have a look at this tommorrow.
^ permalink raw reply
* Re: [PATCH 11/11] netlink: add documentation for memory mapped I/O
From: Patrick McHardy @ 2012-08-22 22:19 UTC (permalink / raw)
To: Jan Engelhardt; +Cc: Florian.Westphal, netdev, netfilter-devel
In-Reply-To: <alpine.LNX.2.01.1208201224430.8114@frira.zrqbmnf.qr>
On Mon, 20 Aug 2012, Jan Engelhardt wrote:
> On Monday 2012-08-20 08:18, Patrick McHardy wrote:
>> +
>> +RX and TX rings
>> +----------------
>> +
>> +Each ring contains a number of continous memory blocks, containing frames of
>> +fixed size dependant on the parameters used for ring setup.
>
> dependent
> [...]
All fixed, thanks.
^ permalink raw reply
* Re: [PATCH 09/18] netfilter: ipv6: add IPv6 NAT support
From: Patrick McHardy @ 2012-08-22 22:15 UTC (permalink / raw)
To: Jan Engelhardt; +Cc: netfilter-devel, netdev
In-Reply-To: <alpine.LNX.2.01.1208201100340.6101@frira.zrqbmnf.qr>
On Mon, 20 Aug 2012, Jan Engelhardt wrote:
> On Monday 2012-08-20 05:39, Patrick McHardy wrote:
>> +static struct nf_hook_ops nf_nat_ipv6_ops[] __read_mostly = {
>> + /* Before packet filtering, change destination */
>> + {
>> + .hook = nf_nat_ipv6_in,
>> + .owner = THIS_MODULE,
>> + .pf = NFPROTO_IPV6,
>> + .hooknum = NF_INET_PRE_ROUTING,
>> + .priority = NF_IP_PRI_NAT_DST,
>
> NF_IP6_PRI_NAT_DST
>
>> + .hook = nf_nat_ipv6_out,
>> + .owner = THIS_MODULE,
>> + .pf = NFPROTO_IPV6,
>> + .hooknum = NF_INET_POST_ROUTING,
>> + .priority = NF_IP_PRI_NAT_SRC,
>
> IP6 too... (2 more occurrences)
Fixed, thanks.
>> +static void nf_nat_ipv6_csum_recalc(struct sk_buff *skb,
>> + u8 proto, void *data, __sum16 *check,
>> + int datalen, int oldlen)
>> +{
>> + const struct ipv6hdr *ipv6h = ipv6_hdr(skb);
>> + struct rt6_info *rt = (struct rt6_info *)skb_dst(skb);
>> +
>> + if (skb->ip_summed != CHECKSUM_PARTIAL) {
>
> Maybe invert to == CHECKSUM_PARTIAL like in p06/18.
I didn't change the other patch.
^ permalink raw reply
* Re: [PATCH 06/18] netfilter: add protocol independant NAT core
From: Patrick McHardy @ 2012-08-22 22:13 UTC (permalink / raw)
To: Jan Engelhardt; +Cc: netfilter-devel, netdev
In-Reply-To: <alpine.LNX.2.01.1208201011480.6101@frira.zrqbmnf.qr>
On Mon, 20 Aug 2012, Jan Engelhardt wrote:
> On Monday 2012-08-20 05:39, Patrick McHardy wrote:
>>
>> enum ctattr_nat {
>> CTA_NAT_UNSPEC,
>> - CTA_NAT_MINIP,
>> - CTA_NAT_MAXIP,
>> + CTA_NAT_V4_MINIP,
>> +#define CTA_NAT_MINIP CTA_NAT_V4_MINIP
>> + CTA_NAT_V4_MAXIP,
>> +#define CTA_NAT_MAXIP CTA_NAT_V4_MAXIP
>> CTA_NAT_PROTO,
>> __CTA_NAT_MAX
>> };
>
> One could also
>
> enum ctattr_nat {
> ...
> __CTA_NAT_MAX,
>
> CTA_NAT_MINIP = CTA_NAT_V4_MINIP,
> CTA_NAT_MAXIP = CTA_NAT_V4_MAXIP,
> };
>
> to provide the old names.
Sure. Doesn't really matter since defines are not used consistently
(in which case you could use them for #ifdefs).
>> diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig
>> index fcc543c..33372a1 100644
>> --- a/net/ipv4/netfilter/Kconfig
>> +++ b/net/ipv4/netfilter/Kconfig
> [...]
>>
>> -config NF_NAT_NEEDED
>> - bool
>> - depends on NF_NAT
>> - default y
>> -
>
> Could add "if NF_NAT_IPV4".."endif" block as appropriate around here,
> to save on all the extra "depend on NF_NAT_IPV4" clauses.
Agreed.
>> +static int nf_nat_ipv4_in_range(const struct nf_conntrack_tuple *t,
>> + const struct nf_nat_range *range)
>> +{
>> + return ntohl(t->src.u3.ip) >= ntohl(range->min_addr.ip) &&
>> + ntohl(t->src.u3.ip) <= ntohl(range->max_addr.ip);
>> +}
>
> static bool ..
Changed.
>> +static bool nf_nat_ipv4_manip_pkt(struct sk_buff *skb,
>> + unsigned int iphdroff,
>> + const struct nf_nat_l4proto *l4proto,
>> + const struct nf_conntrack_tuple *target,
>> + enum nf_nat_manip_type maniptype)
>> +{
>> + struct iphdr *iph;
>> + unsigned int hdroff;
>> +
>> + if (!skb_make_writable(skb, iphdroff + sizeof(*iph)))
>> + return false;
>> +
>> + iph = (void *)skb->data + iphdroff;
>
> Is iph = ip_hdr(skb), hdroff = iphdroff+skb_iphdrlen(iph) not usable here?
No, we're also translating the inner packets in ICMP error messages.
>> + hdroff = iphdroff + iph->ihl * 4;
>> +
>> + if (!l4proto->manip_pkt(skb, &nf_nat_l3proto_ipv4, iphdroff, hdroff,
>> + target, maniptype))
>> + return false;
>> + iph = (void *)skb->data + iphdroff;
>
> Is trying to avoid some GNU extensions a worthwhile goal? If so,
> iph = (struct iphdr *)(skb->data + iphdroff) should be used, like in:
I don't get your point.
>> +static void nf_nat_ipv4_csum_update(struct sk_buff *skb,
>> + unsigned int iphdroff, __sum16 *check,
>> + const struct nf_conntrack_tuple *t,
>> + enum nf_nat_manip_type maniptype)
>> +{
>> + struct iphdr *iph = (struct iphdr *)(skb->data + iphdroff);
>> [...]
>> +}
>
>
>
>> +static void nf_nat_ipv4_csum_recalc(struct sk_buff *skb,
>> + u8 proto, void *data, __sum16 *check,
>> + int datalen, int oldlen)
>> +{
>> + const struct iphdr *iph = ip_hdr(skb);
>> + struct rtable *rt = skb_rtable(skb);
>> +
>> + if (skb->ip_summed != CHECKSUM_PARTIAL) {
>> + if (!(rt->rt_flags & RTCF_LOCAL) &&
>> + (!skb->dev || skb->dev->features & NETIF_F_V4_CSUM)) {
>> + skb->ip_summed = CHECKSUM_PARTIAL;
>> + skb->csum_start = skb_headroom(skb) +
>> + skb_network_offset(skb) +
>> + ip_hdrlen(skb);
>> + skb->csum_offset = (void *)check - data;
>> + *check = ~csum_tcpudp_magic(iph->saddr, iph->daddr,
>> + datalen, proto, 0);
>> + } else {
>> + *check = 0;
>> + *check = csum_tcpudp_magic(iph->saddr, iph->daddr,
>> + datalen, proto,
>> + csum_partial(data, datalen,
>> + 0));
>> + if (proto == IPPROTO_UDP && !*check)
>> + *check = CSUM_MANGLED_0;
>> + }
>> + } else
>> + inet_proto_csum_replace2(check, skb,
>> + htons(oldlen), htons(datalen), 1);
>> +}
>
> Here is a style factory trick: invert the condition such that the
> simple case is first, and the big one becomes an else if
> with a reduced indent:
This is existing code, I don't want to bloat the diff by unnecessarily
rearranging it.
>> +static void __exit nf_nat_l3proto_ipv4_exit(void)
>> +{
>> + nf_nat_l3proto_unregister(&nf_nat_l3proto_ipv4);
>> + nf_nat_l4proto_unregister(NFPROTO_IPV4, &nf_nat_l4proto_icmp);
>> +}
>> +
>> +MODULE_LICENSE("GPL");
>> +MODULE_ALIAS("nf-nat-" __stringify(AF_INET));
>
> Technically, this would have to be NFPROTO_IPV4, though GNU C has yet
> to gain an extension to stringify enum constants..
I'm aware of that.
>> + /* 1) If this srcip/proto/src-proto-part is currently mapped,
>> + * and that same mapping gives a unique tuple within the given
>> + * range, use that.
>> + *
>> + * This is only required for source (ie. NAT/masq) mappings.
>> + * So far, we don't do local source mappings, so multiple
>> + * manips not an issue.
> manips are not an issue.
>
>
>> - /* nf_conntrack_alter_reply might re-allocate extension area */
>> + /* nf_conntrack_alter_reply might re-allocate exntension aera */
>
> extension was correct :)
Fixed, thanks.
>> + .target = xt_snat_target_v1,
>> + .targetsize = sizeof(struct nf_nat_range),
>> + .table = "nat",
>> + .hooks = (1 << NF_INET_POST_ROUTING) |
>> + (1 << NF_INET_LOCAL_OUT),
>> + .me = THIS_MODULE,
>
> .family = NFPROTO_UNSPEC,
>
> Just for completeness.
This is obvious.
^ permalink raw reply
* [PATCH] netdev/phy: add MDIO bus multiplexer driven by a memory-mapped FPGA
From: Timur Tabi @ 2012-08-22 21:45 UTC (permalink / raw)
To: Andy Fleming, David Miller, netdev, david.daney
An FPGA controls which sub-bus is connected to the master MDIO bus. The
FPGA must be memory-mapped and contain only 8-bit registers (which keeps
things simple).
Tested on a Freescale P5020DS board which uses the "PIXIS" FPGA attached
to the localbus.
Signed-off-by: Timur Tabi <timur@freescale.com>
---
.../devicetree/bindings/net/mdio-mux-fpga.txt | 74 ++++++++
drivers/net/phy/Kconfig | 13 ++
drivers/net/phy/Makefile | 1 +
drivers/net/phy/mdio-mux-fpga.c | 186 ++++++++++++++++++++
4 files changed, 274 insertions(+), 0 deletions(-)
create mode 100644 Documentation/devicetree/bindings/net/mdio-mux-fpga.txt
create mode 100644 drivers/net/phy/mdio-mux-fpga.c
diff --git a/Documentation/devicetree/bindings/net/mdio-mux-fpga.txt b/Documentation/devicetree/bindings/net/mdio-mux-fpga.txt
new file mode 100644
index 0000000..ef567c6
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/mdio-mux-fpga.txt
@@ -0,0 +1,74 @@
+Properties for an MDIO bus multiplexer/switch controlled by an FPGA register.
+
+This is a special case of a MDIO bus multiplexer. An FPGA register is used
+to control which child bus is connected.
+
+Required properties in addition to the generic multiplexer properties:
+
+- compatible : string, must contain "mdio-mux-fpga"
+
+- mdio-mux-device : phandle, points to the FPGA (or similar) node. This
+ must be a memory-mapped device with 8-bit registers.
+
+- mdio-mux-register : integer, contains the offset of the register that
+ controls the bus multiplexer.
+
+- mdio-mux-mask : integer, contains an 8-bit mask that specifies which
+ bits in the register control the actual bus multiplexer. The
+ 'reg' property of each child mdio-mux node must be constrained by
+ this mask.
+
+Example:
+
+The FPGA node defines a memory-mapped FPGA with a register space of 0x30 bytes.
+For the "EMI2" MDIO bus, register 9 (BRDCFG1) controls the mux on that bus.
+A bitmask of 0x6 means that bits 1 and 2 (bit 0 is lsb) are the bits on
+BRDCFG1 that control the actual mux.
+
+ /* The FPGA node */
+ fpga: board-control@3,0 {
+ compatible = "fsl,p5020ds-fpga", "fsl,fpga-ngpixis";
+ reg = <3 0 0x30>;
+ };
+
+ /* The parent MDIO bus. */
+ xmdio0: mdio@f1000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,fman-xmdio";
+ reg = <0xf1000 0x1000>;
+ interrupts = <100 1 0 0>;
+ };
+
+ mdio-mux-emi2 {
+ compatible = "mdio-mux-fpga", "mdio-mux";
+ mdio-parent-bus = <&xmdio0>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ mdio-mux-device = <&fpga>;
+ mdio-mux-register = <9>; // BRDCFG1
+ mdio-mux-mask = <0x6>; // EMI2
+
+ emi2_slot1: mdio@0 { // Slot 1 XAUI (FM2)
+ reg = <0>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ phy_xgmii_slot1: ethernet-phy@0 {
+ compatible = "ethernet-phy-ieee802.3-c45";
+ reg = <4>;
+ };
+ };
+
+ emi2_slot2: mdio@2 { // Slot 2 XAUI (FM1)
+ reg = <2>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ phy_xgmii_slot2: ethernet-phy@4 {
+ compatible = "ethernet-phy-ieee802.3-c45";
+ reg = <0>;
+ };
+ };
+ };
+
diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
index 3090dc6..c3fc957 100644
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -159,6 +159,19 @@ config MDIO_BUS_MUX_GPIO
several child MDIO busses to a parent bus. Child bus
selection is under the control of GPIO lines.
+config MDIO_BUS_MUX_FPGA
+ tristate "Support for FPGA-controlled MDIO bus multiplexers"
+ depends on OF_MDIO
+ select MDIO_BUS_MUX
+ help
+ This module provides a driver for MDIO bus multiplexers that
+ are controlled via a simple memory-mapped FPGA device. The
+ multiplexer connects one of several child MDIO busses to a parent
+ bus. Child bus selection is under the control of one of the
+ FPGA's registers.
+
+ Currently, only 8-bit registers are supported.
+
endif # PHYLIB
config MICREL_KS8995MA
diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
index 6d2dc6c..3bf4d7a 100644
--- a/drivers/net/phy/Makefile
+++ b/drivers/net/phy/Makefile
@@ -28,3 +28,4 @@ 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
+obj-$(CONFIG_MDIO_BUS_MUX_FPGA) += mdio-mux-fpga.o
diff --git a/drivers/net/phy/mdio-mux-fpga.c b/drivers/net/phy/mdio-mux-fpga.c
new file mode 100644
index 0000000..7b4e69c
--- /dev/null
+++ b/drivers/net/phy/mdio-mux-fpga.c
@@ -0,0 +1,186 @@
+/*
+ * FPGA MDIO MUX driver
+ *
+ * This driver supports
+ * Author: Timur Tabi <timur@freescale.com>
+ *
+ * Copyright 2012 Freescale Semiconductor, Inc.
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#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>
+
+struct mdio_mux_fpga_state {
+ void *mux_handle;
+ phys_addr_t phys;
+ unsigned int offset;
+ uint8_t mask;
+};
+
+/*
+ * MDIO multiplexing switch function
+ *
+ * This function is called by the mdio-mux layer when it thinks the mdio bus
+ * multiplexer needs to switch.
+ *
+ * 'current_child' is the current value of the mux register (masked via
+ * s->mask).
+ *
+ * 'desired_child' is the value of the 'reg' property of the target child MDIO
+ * node.
+ *
+ * The first time this function is called, current_child == -1.
+ *
+ * If current_child == desired_child, then the mux is already set to the
+ * correct bus.
+ */
+static int mdio_mux_fpga_switch_fn(int current_child, int desired_child,
+ void *data)
+{
+ struct mdio_mux_fpga_state *s = data;
+
+ if (current_child ^ desired_child) {
+ void *p = ioremap(s->phys + s->offset, 1);
+ uint8_t x;
+
+ if (!p)
+ return -ENOMEM;
+
+ x = ioread8(p);
+ iowrite8((x & ~s->mask) | desired_child, p);
+
+ iounmap(p);
+ }
+
+ return 0;
+}
+
+static int __devinit mdio_mux_fpga_probe(struct platform_device *pdev)
+{
+ struct device_node *np2, *np = pdev->dev.of_node;
+ struct mdio_mux_fpga_state *s;
+ struct resource res;
+ const __be32 *iprop;
+ int len, ret;
+
+ dev_dbg(&pdev->dev, "probing node %s\n", np->full_name);
+
+ s = devm_kzalloc(&pdev->dev, sizeof(*s), GFP_KERNEL);
+ if (!s)
+ return -ENOMEM;
+
+ iprop = of_get_property(np, "mdio-mux-device", &len);
+ if (!iprop || len != sizeof(phandle)) {
+ dev_err(&pdev->dev, "missing mdio-mux-device property\n");
+ return -ENODEV;
+ }
+ np2 = of_find_node_by_phandle(be32_to_cpup(iprop));
+ if (!np2) {
+ dev_err(&pdev->dev, "mdio-mux-device points to invalid node\n");
+ return -ENODEV;
+ }
+
+ ret = of_address_to_resource(np2, 0, &res);
+ if (ret) {
+ dev_err(&pdev->dev, "cannot obtain memory map for node %s\n",
+ np2->full_name);
+ return ret;
+ }
+ s->phys = res.start;
+
+ iprop = of_get_property(np, "mdio-mux-register", &len);
+ if (!iprop || len != sizeof(uint32_t)) {
+ dev_err(&pdev->dev, "missing mdio-mux-register property\n");
+ return -EINVAL;
+ }
+ s->offset = be32_to_cpup(iprop);
+ if (s->offset >= resource_size(&res)) {
+ dev_err(&pdev->dev, "mdio-mux-register value %u is too large\n",
+ s->offset);
+ return -EINVAL;
+ }
+
+ iprop = of_get_property(np, "mdio-mux-mask", &len);
+ if (!iprop || len != sizeof(uint32_t)) {
+ dev_err(&pdev->dev, "missing mdio-mux-mask property\n");
+ return -ENODEV;
+ }
+ if (be32_to_cpup(iprop) > 255) {
+ dev_err(&pdev->dev, "only 8-bit registers are supported\n");
+ return -EINVAL;
+ }
+ s->mask = be32_to_cpup(iprop);
+
+ /*
+ * Verify that the 'reg' property of each child MDIO bus does not
+ * set any bits outside of the 'mask'.
+ */
+ for_each_available_child_of_node(np, np2) {
+ iprop = of_get_property(np2, "reg", &len);
+ if (!iprop || len != sizeof(uint32_t)) {
+ dev_err(&pdev->dev, "mdio-mux child node %s is "
+ "missing a 'reg' property\n", np2->full_name);
+ return -ENODEV;
+ }
+ if (be32_to_cpup(iprop) & ~s->mask) {
+ dev_err(&pdev->dev, "mdio-mux child node %s has "
+ "a 'reg' value with unmasked bits\n",
+ np2->full_name);
+ return -ENODEV;
+ }
+ }
+
+ ret = mdio_mux_init(&pdev->dev, mdio_mux_fpga_switch_fn,
+ &s->mux_handle, s);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to register mdio-mux bus %s\n",
+ np->full_name);
+ return ret;
+ }
+
+ pdev->dev.platform_data = s;
+
+ return 0;
+}
+
+static int __devexit mdio_mux_fpga_remove(struct platform_device *pdev)
+{
+ struct mdio_mux_fpga_state *s = dev_get_platdata(&pdev->dev);
+
+ mdio_mux_uninit(s->mux_handle);
+
+ return 0;
+}
+
+static struct of_device_id mdio_mux_fpga_match[] = {
+ {
+ .compatible = "mdio-mux-fpga",
+ },
+ {},
+};
+MODULE_DEVICE_TABLE(of, mdio_mux_fpga_match);
+
+static struct platform_driver mdio_mux_fpga_driver = {
+ .driver = {
+ .name = "mdio-mux-fpga",
+ .owner = THIS_MODULE,
+ .of_match_table = mdio_mux_fpga_match,
+ },
+ .probe = mdio_mux_fpga_probe,
+ .remove = __devexit_p(mdio_mux_fpga_remove),
+};
+
+module_platform_driver(mdio_mux_fpga_driver);
+
+MODULE_AUTHOR("Timur Tabi <timur@freescale.com>");
+MODULE_DESCRIPTION("FPGA MDIO MUX driver");
+MODULE_LICENSE("GPL v2");
--
1.7.3.4
^ permalink raw reply related
* Re: [PATCH 00/18] netfilter: IPv6 NAT
From: David Miller @ 2012-08-22 21:42 UTC (permalink / raw)
To: kaber; +Cc: netfilter-devel, netdev
In-Reply-To: <Pine.GSO.4.63.1208222322060.25423@stinky-local.trash.net>
From: Patrick McHardy <kaber@trash.net>
Date: Wed, 22 Aug 2012 23:23:53 +0200 (MEST)
> The NAT patches depend on a couple of fixes in Pablo's latest
> submission, if you could merge net.git into net-next.git, I can push
> them to Pablo without creating conflicts. Thanks!
I just did that right now, should show up on kernel.org shortly.
^ permalink raw reply
* Re: [PATCH 2/3] x86_64: Define 128-bit memory-mapped I/O operations
From: David Miller @ 2012-08-22 21:38 UTC (permalink / raw)
To: torvalds; +Cc: hpa, bhutchings, tglx, mingo, netdev, linux-net-drivers, x86
In-Reply-To: <CA+55aFxxSFMiohu80BZCObA0APPe08h1-7eAZ_BLoAZDWqqv0Q@mail.gmail.com>
From: Linus Torvalds <torvalds@linux-foundation.org>
Date: Wed, 22 Aug 2012 14:28:50 -0700
> On Wed, Aug 22, 2012 at 2:14 PM, David Miller <davem@davemloft.net> wrote:
>>
>> BTW, just to clarify, I'm not saying that we should save the FPU on
>> every trap where we find the FPU enabled or anything stupid like that.
>>
>> Definitely keep the kern_fpu_begin()/kern_fpu_end() type markers
>> around FPU usage, but allow some kind of nesting facility.
>
> So nesting shouldn't be horrible, but the thing that really screws
> with people like the crypto use is not nesting, but the fact that
> sometimes you can't save at all, and the whole "kernel_fpu_possible()"
> or whatever we call the checking function.
>
> IOW, in [soft]irq context, to avoid races with the irq happening as
> the process is going to do something with the FPU state, we don't
> allow saving and changing state, because that would mean that the
> normal FP state paths would have to be irq-safe, and they aren't.
>
> And once you have to have that fpu possible check, if it happens to
> also disallow nested use, I doubt that's going to really affect
> anybody. The code has to take the case of "I'm not allowed to change
> FPU state" case into account regardless.
I don't think you really have to do anything special to handle
interrupts properly.
Let's assume that we use some variable length save area at the end of
thread_info to do this nested saving.
When you are asked for FPU usage, you first figure out how much you're
going to save.
Then you advance the allocation pointer in the thread_info, and save
into the space you allocated.
If an interrupt wants to use the FPU, that should be fine as well.
Whether the interrupt FPU save does it's save after you did, or
before, it should work out fine.
I suppose you might have some issues in determining whether we need to
do the full fxsave stuff or not. There could be a state bit for that,
or similar.
Another idea, instead of doing this in thread_info, is to do it on the
local stack. That way if we're in an interrupt, we'll use that
interrupt type's kernel stack.
You might be able to get away with always doing the full FPU
save/restore in that situation.
^ permalink raw reply
* Re: [PATCH 2/3] x86_64: Define 128-bit memory-mapped I/O operations
From: Linus Torvalds @ 2012-08-22 21:28 UTC (permalink / raw)
To: David Miller; +Cc: hpa, bhutchings, tglx, mingo, netdev, linux-net-drivers, x86
In-Reply-To: <20120822.141433.730254311852927123.davem@davemloft.net>
On Wed, Aug 22, 2012 at 2:14 PM, David Miller <davem@davemloft.net> wrote:
>
> BTW, just to clarify, I'm not saying that we should save the FPU on
> every trap where we find the FPU enabled or anything stupid like that.
>
> Definitely keep the kern_fpu_begin()/kern_fpu_end() type markers
> around FPU usage, but allow some kind of nesting facility.
So nesting shouldn't be horrible, but the thing that really screws
with people like the crypto use is not nesting, but the fact that
sometimes you can't save at all, and the whole "kernel_fpu_possible()"
or whatever we call the checking function.
IOW, in [soft]irq context, to avoid races with the irq happening as
the process is going to do something with the FPU state, we don't
allow saving and changing state, because that would mean that the
normal FP state paths would have to be irq-safe, and they aren't.
And once you have to have that fpu possible check, if it happens to
also disallow nested use, I doubt that's going to really affect
anybody. The code has to take the case of "I'm not allowed to change
FPU state" case into account regardless.
Linus
^ permalink raw reply
* Re: [net-next 0/6][pull request] Intel Wired LAN Driver Updates
From: David Miller @ 2012-08-22 21:24 UTC (permalink / raw)
To: jeffrey.t.kirsher; +Cc: netdev, gospo, sassmann
In-Reply-To: <1345538275-1690-1-git-send-email-jeffrey.t.kirsher@intel.com>
From: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Date: Tue, 21 Aug 2012 01:37:49 -0700
> This series contains updates to ethtool.h, e1000, e1000e, and igb to
> implement MDI/MDIx control.
>
> The following are changes since commit 1d76efe1577b4323609b1bcbfafa8b731eda071a:
> team: add support for non-ethernet devices
> and are available in the git repository at:
> git://git.kernel.org/pub/scm/linux/kernel/git/jkirsher/net-next master
Pulled, thanks Jeff.
^ 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