[PATCH 3.10 39/54] ipv6: probe routes asynchronous in rt6_probe

2013-11-01 Thread Greg Kroah-Hartman
3.10-stable review patch.  If anyone has any objections, please let me know.

--

From: Hannes Frederic Sowa 

[ Upstream commit c2f17e827b419918c856131f592df9521e1a38e3 ]

Routes need to be probed asynchronous otherwise the call stack gets
exhausted when the kernel attemps to deliver another skb inline, like
e.g. xt_TEE does, and we probe at the same time.

We update neigh->updated still at once, otherwise we would send to
many probes.

Cc: Julian Anastasov 
Signed-off-by: Hannes Frederic Sowa 
Signed-off-by: David S. Miller 
Signed-off-by: Greg Kroah-Hartman 
---
 net/ipv6/route.c |   38 +++---
 1 file changed, 31 insertions(+), 7 deletions(-)

--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -473,6 +473,24 @@ out:
 }
 
 #ifdef CONFIG_IPV6_ROUTER_PREF
+struct __rt6_probe_work {
+   struct work_struct work;
+   struct in6_addr target;
+   struct net_device *dev;
+};
+
+static void rt6_probe_deferred(struct work_struct *w)
+{
+   struct in6_addr mcaddr;
+   struct __rt6_probe_work *work =
+   container_of(w, struct __rt6_probe_work, work);
+
+   addrconf_addr_solict_mult(>target, );
+   ndisc_send_ns(work->dev, NULL, >target, , NULL);
+   dev_put(work->dev);
+   kfree(w);
+}
+
 static void rt6_probe(struct rt6_info *rt)
 {
struct neighbour *neigh;
@@ -496,17 +514,23 @@ static void rt6_probe(struct rt6_info *r
 
if (!neigh ||
time_after(jiffies, neigh->updated + 
rt->rt6i_idev->cnf.rtr_probe_interval)) {
-   struct in6_addr mcaddr;
-   struct in6_addr *target;
+   struct __rt6_probe_work *work;
 
-   if (neigh) {
+   work = kmalloc(sizeof(*work), GFP_ATOMIC);
+
+   if (neigh && work)
neigh->updated = jiffies;
+
+   if (neigh)
write_unlock(>lock);
-   }
 
-   target = (struct in6_addr *)>rt6i_gateway;
-   addrconf_addr_solict_mult(target, );
-   ndisc_send_ns(rt->dst.dev, NULL, target, , NULL);
+   if (work) {
+   INIT_WORK(>work, rt6_probe_deferred);
+   work->target = rt->rt6i_gateway;
+   dev_hold(rt->dst.dev);
+   work->dev = rt->dst.dev;
+   schedule_work(>work);
+   }
} else {
 out:
write_unlock(>lock);


--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 3.10 39/54] ipv6: probe routes asynchronous in rt6_probe

2013-11-01 Thread Greg Kroah-Hartman
3.10-stable review patch.  If anyone has any objections, please let me know.

--

From: Hannes Frederic Sowa han...@stressinduktion.org

[ Upstream commit c2f17e827b419918c856131f592df9521e1a38e3 ]

Routes need to be probed asynchronous otherwise the call stack gets
exhausted when the kernel attemps to deliver another skb inline, like
e.g. xt_TEE does, and we probe at the same time.

We update neigh-updated still at once, otherwise we would send to
many probes.

Cc: Julian Anastasov j...@ssi.bg
Signed-off-by: Hannes Frederic Sowa han...@stressinduktion.org
Signed-off-by: David S. Miller da...@davemloft.net
Signed-off-by: Greg Kroah-Hartman gre...@linuxfoundation.org
---
 net/ipv6/route.c |   38 +++---
 1 file changed, 31 insertions(+), 7 deletions(-)

--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -473,6 +473,24 @@ out:
 }
 
 #ifdef CONFIG_IPV6_ROUTER_PREF
+struct __rt6_probe_work {
+   struct work_struct work;
+   struct in6_addr target;
+   struct net_device *dev;
+};
+
+static void rt6_probe_deferred(struct work_struct *w)
+{
+   struct in6_addr mcaddr;
+   struct __rt6_probe_work *work =
+   container_of(w, struct __rt6_probe_work, work);
+
+   addrconf_addr_solict_mult(work-target, mcaddr);
+   ndisc_send_ns(work-dev, NULL, work-target, mcaddr, NULL);
+   dev_put(work-dev);
+   kfree(w);
+}
+
 static void rt6_probe(struct rt6_info *rt)
 {
struct neighbour *neigh;
@@ -496,17 +514,23 @@ static void rt6_probe(struct rt6_info *r
 
if (!neigh ||
time_after(jiffies, neigh-updated + 
rt-rt6i_idev-cnf.rtr_probe_interval)) {
-   struct in6_addr mcaddr;
-   struct in6_addr *target;
+   struct __rt6_probe_work *work;
 
-   if (neigh) {
+   work = kmalloc(sizeof(*work), GFP_ATOMIC);
+
+   if (neigh  work)
neigh-updated = jiffies;
+
+   if (neigh)
write_unlock(neigh-lock);
-   }
 
-   target = (struct in6_addr *)rt-rt6i_gateway;
-   addrconf_addr_solict_mult(target, mcaddr);
-   ndisc_send_ns(rt-dst.dev, NULL, target, mcaddr, NULL);
+   if (work) {
+   INIT_WORK(work-work, rt6_probe_deferred);
+   work-target = rt-rt6i_gateway;
+   dev_hold(rt-dst.dev);
+   work-dev = rt-dst.dev;
+   schedule_work(work-work);
+   }
} else {
 out:
write_unlock(neigh-lock);


--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/