Re: [PATCH net-next v2] ipv6: Do not iterate over all interfaces when finding source address on specific interface.

2015-07-13 Thread YOSHIFUJI Hideaki
Hi,

Hajime Tazaki wrote:
> 
> Yoshifuji-san,
> 
> At Mon, 13 Jul 2015 17:38:48 +0900,
> Erik Kline wrote:
>>
>> On 13 July 2015 at 15:32, YOSHIFUJI Hideaki
>>  wrote:
>>> Hi,
>>>
>>> Erik Kline wrote:
 Hmm, when I run a UML linux with this patch (which, I'm ashamed to
 say, I failed to do before) I get these kinds of errors:

 unregister_netdevice: waiting for  to become free.
 Usage count = 1
 unregister_netdevice: waiting for  to become free.
 Usage count = 1

 Perhaps they're unrelated... I'm still investigating.
>>>
>>> Would you test attached patch please?
>>
>> That does look logically correct, so +1 to it regardless, but it does
>> not seem to have fixed the issue I'm seeing.
>>
>> I still haven't produced the smallest possible demo test program.
> 
> sorry to jump-in, but there is a side-effect with this
> patch, which my tcp and dccp tests (ipv6) are failed.
> 
> because newly added function (__ipv6_dev_get_saddr) won't
> update a variable 'hiscore' (it swaps with 'score' in some
> case), the caller (ipv6_dev_get_saddr) can't fill an
> appropriate saddr in the end.
> 
> I don't know if this is a good patch but the following diff
> makes my test happy.

We should update score as well...

> 
> -- Hajime
> 
> diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
> index 4ab74d5..c4e9416 100644
> --- a/net/ipv6/addrconf.c
> +++ b/net/ipv6/addrconf.c
> @@ -1363,7 +1363,8 @@ static void __ipv6_dev_get_saddr(struct net *net,
>unsigned int prefs,
>const struct in6_addr *saddr,
>struct inet6_dev *idev,
> -  struct ipv6_saddr_score *scores)
> +  struct ipv6_saddr_score *scores,
> +  struct ipv6_saddr_score **in_hiscore)
>  {
>   struct ipv6_saddr_score *score = &scores[0], *hiscore = &scores[1];
>  
> @@ -1424,6 +1425,7 @@ static void __ipv6_dev_get_saddr(struct net *net,
>   in6_ifa_hold(score->ifa);
>  
>   swap(hiscore, score);
> + *in_hiscore = hiscore;
>  
>   /* restore our iterator */
>   score->ifa = hiscore->ifa;
> @@ -1480,13 +1482,15 @@ int ipv6_dev_get_saddr(struct net *net, const struct 
> net_device *dst_dev,
>   }
>  
>   if (use_oif_addr) {
> - __ipv6_dev_get_saddr(net, &dst, prefs, saddr, idev, scores);
> + __ipv6_dev_get_saddr(net, &dst, prefs, saddr, idev,
> +  scores, &hiscore);
>   } else {
>   for_each_netdev_rcu(net, dev) {
>   idev = __in6_dev_get(dev);
>   if (!idev)
>   continue;
> - __ipv6_dev_get_saddr(net, &dst, prefs, saddr, idev, 
> scores);
> + __ipv6_dev_get_saddr(net, &dst, prefs, saddr, idev,
> +  scores, &hiscore);
>   }
>   }
>   rcu_read_unlock();
> 

-- 
Hideaki Yoshifuji 
Technical Division, MIRACLE LINUX CORPORATION
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH net-next v2] ipv6: Do not iterate over all interfaces when finding source address on specific interface.

2015-07-13 Thread Hajime Tazaki

Yoshifuji-san,

At Mon, 13 Jul 2015 17:38:48 +0900,
Erik Kline wrote:
> 
> On 13 July 2015 at 15:32, YOSHIFUJI Hideaki
>  wrote:
> > Hi,
> >
> > Erik Kline wrote:
> >> Hmm, when I run a UML linux with this patch (which, I'm ashamed to
> >> say, I failed to do before) I get these kinds of errors:
> >>
> >> unregister_netdevice: waiting for  to become free.
> >> Usage count = 1
> >> unregister_netdevice: waiting for  to become free.
> >> Usage count = 1
> >>
> >> Perhaps they're unrelated... I'm still investigating.
> >
> > Would you test attached patch please?
> 
> That does look logically correct, so +1 to it regardless, but it does
> not seem to have fixed the issue I'm seeing.
> 
> I still haven't produced the smallest possible demo test program.

sorry to jump-in, but there is a side-effect with this
patch, which my tcp and dccp tests (ipv6) are failed.

because newly added function (__ipv6_dev_get_saddr) won't
update a variable 'hiscore' (it swaps with 'score' in some
case), the caller (ipv6_dev_get_saddr) can't fill an
appropriate saddr in the end.

I don't know if this is a good patch but the following diff
makes my test happy.

-- Hajime

diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 4ab74d5..c4e9416 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -1363,7 +1363,8 @@ static void __ipv6_dev_get_saddr(struct net *net,
 unsigned int prefs,
 const struct in6_addr *saddr,
 struct inet6_dev *idev,
-struct ipv6_saddr_score *scores)
+struct ipv6_saddr_score *scores,
+struct ipv6_saddr_score **in_hiscore)
 {
struct ipv6_saddr_score *score = &scores[0], *hiscore = &scores[1];
 
@@ -1424,6 +1425,7 @@ static void __ipv6_dev_get_saddr(struct net *net,
in6_ifa_hold(score->ifa);
 
swap(hiscore, score);
+   *in_hiscore = hiscore;
 
/* restore our iterator */
score->ifa = hiscore->ifa;
@@ -1480,13 +1482,15 @@ int ipv6_dev_get_saddr(struct net *net, const struct 
net_device *dst_dev,
}
 
if (use_oif_addr) {
-   __ipv6_dev_get_saddr(net, &dst, prefs, saddr, idev, scores);
+   __ipv6_dev_get_saddr(net, &dst, prefs, saddr, idev,
+scores, &hiscore);
} else {
for_each_netdev_rcu(net, dev) {
idev = __in6_dev_get(dev);
if (!idev)
continue;
-   __ipv6_dev_get_saddr(net, &dst, prefs, saddr, idev, 
scores);
+   __ipv6_dev_get_saddr(net, &dst, prefs, saddr, idev,
+scores, &hiscore);
}
}
rcu_read_unlock();
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH net-next v2] ipv6: Do not iterate over all interfaces when finding source address on specific interface.

2015-07-13 Thread Erik Kline
On 13 July 2015 at 15:32, YOSHIFUJI Hideaki
 wrote:
> Hi,
>
> Erik Kline wrote:
>> Hmm, when I run a UML linux with this patch (which, I'm ashamed to
>> say, I failed to do before) I get these kinds of errors:
>>
>> unregister_netdevice: waiting for  to become free.
>> Usage count = 1
>> unregister_netdevice: waiting for  to become free.
>> Usage count = 1
>>
>> Perhaps they're unrelated... I'm still investigating.
>
> Would you test attached patch please?

That does look logically correct, so +1 to it regardless, but it does
not seem to have fixed the issue I'm seeing.

I still haven't produced the smallest possible demo test program.
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH net-next v2] ipv6: Do not iterate over all interfaces when finding source address on specific interface.

2015-07-12 Thread YOSHIFUJI Hideaki
Hi,

Erik Kline wrote:
> Hmm, when I run a UML linux with this patch (which, I'm ashamed to
> say, I failed to do before) I get these kinds of errors:
> 
> unregister_netdevice: waiting for  to become free.
> Usage count = 1
> unregister_netdevice: waiting for  to become free.
> Usage count = 1
> 
> Perhaps they're unrelated... I'm still investigating.

Would you test attached patch please?

--yoshfuji

> 
> On 11 July 2015 at 15:19, David Miller  wrote:
>> From: YOSHIFUJI Hideaki/吉藤英明 
>> Date: Fri, 10 Jul 2015 16:58:31 +0900
>>
>>> If outgoing interface is specified and the candidate address is
>>> restricted to the outgoing interface, it is enough to iterate
>>> over that given interface only.
>>>
>>> Signed-off-by: YOSHIFUJI Hideaki 
>>> Acked-by: Erik Kline 
>>
>> Applied, thanks!

-- 
Hideaki Yoshifuji 
Technical Division, MIRACLE LINUX CORPORATION
>From 38c5a10a5876ea47766ffc05b5a131a210d6e1aa Mon Sep 17 00:00:00 2001
From: YOSHIFUJI Hideaki 
Date: Mon, 13 Jul 2015 15:23:02 +0900
Subject: [PATCH] ipv6: Avoid NULL pointer dereference in
 __ipv6_dev_get_saddr().

Commit 9131f3de2 ("ipv6: Do not iterate over all interfaces when
finding source address on specific interface.") introduced
possible NULL pointer dereference if outgoing device is
specified.

Fixes: 9131f3de24db4dc12199aede7d931e6703e97f3b ("ipv6: Do not
	iterate over all interfaces when finding source address
	on specific interface.")
Signed-off-by: YOSHIFUJI Hideaki 
---
 net/ipv6/addrconf.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 4ab74d5..50ad476 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -1480,7 +1480,8 @@ int ipv6_dev_get_saddr(struct net *net, const struct net_device *dst_dev,
 	}
 
 	if (use_oif_addr) {
-		__ipv6_dev_get_saddr(net, &dst, prefs, saddr, idev, scores);
+		if (idev)
+			__ipv6_dev_get_saddr(net, &dst, prefs, saddr, idev, scores);
 	} else {
 		for_each_netdev_rcu(net, dev) {
 			idev = __in6_dev_get(dev);
-- 
1.9.1



Re: [PATCH net-next v2] ipv6: Do not iterate over all interfaces when finding source address on specific interface.

2015-07-11 Thread Erik Kline
Hmm, when I run a UML linux with this patch (which, I'm ashamed to
say, I failed to do before) I get these kinds of errors:

unregister_netdevice: waiting for  to become free.
Usage count = 1
unregister_netdevice: waiting for  to become free.
Usage count = 1

Perhaps they're unrelated... I'm still investigating.

On 11 July 2015 at 15:19, David Miller  wrote:
> From: YOSHIFUJI Hideaki/吉藤英明 
> Date: Fri, 10 Jul 2015 16:58:31 +0900
>
>> If outgoing interface is specified and the candidate address is
>> restricted to the outgoing interface, it is enough to iterate
>> over that given interface only.
>>
>> Signed-off-by: YOSHIFUJI Hideaki 
>> Acked-by: Erik Kline 
>
> Applied, thanks!
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH net-next v2] ipv6: Do not iterate over all interfaces when finding source address on specific interface.

2015-07-10 Thread David Miller
From: YOSHIFUJI Hideaki/吉藤英明 
Date: Fri, 10 Jul 2015 16:58:31 +0900

> If outgoing interface is specified and the candidate address is
> restricted to the outgoing interface, it is enough to iterate
> over that given interface only.
> 
> Signed-off-by: YOSHIFUJI Hideaki 
> Acked-by: Erik Kline 

Applied, thanks!
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH net-next v2] ipv6: Do not iterate over all interfaces when finding source address on specific interface.

2015-07-10 Thread YOSHIFUJI Hideaki/吉藤英明
If outgoing interface is specified and the candidate address is
restricted to the outgoing interface, it is enough to iterate
over that given interface only.

Signed-off-by: YOSHIFUJI Hideaki 
Acked-by: Erik Kline 
---
 net/ipv6/addrconf.c | 197 
 1 file changed, 107 insertions(+), 90 deletions(-)

diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 21c2c81..4ab74d5 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -1358,15 +1358,94 @@ out:
return ret;
 }
 
+static void __ipv6_dev_get_saddr(struct net *net,
+struct ipv6_saddr_dst *dst,
+unsigned int prefs,
+const struct in6_addr *saddr,
+struct inet6_dev *idev,
+struct ipv6_saddr_score *scores)
+{
+   struct ipv6_saddr_score *score = &scores[0], *hiscore = &scores[1];
+
+   read_lock_bh(&idev->lock);
+   list_for_each_entry(score->ifa, &idev->addr_list, if_list) {
+   int i;
+
+   /*
+* - Tentative Address (RFC2462 section 5.4)
+*  - A tentative address is not considered
+*"assigned to an interface" in the traditional
+*sense, unless it is also flagged as optimistic.
+* - Candidate Source Address (section 4)
+*  - In any case, anycast addresses, multicast
+*addresses, and the unspecified address MUST
+*NOT be included in a candidate set.
+*/
+   if ((score->ifa->flags & IFA_F_TENTATIVE) &&
+   (!(score->ifa->flags & IFA_F_OPTIMISTIC)))
+   continue;
+
+   score->addr_type = __ipv6_addr_type(&score->ifa->addr);
+
+   if (unlikely(score->addr_type == IPV6_ADDR_ANY ||
+score->addr_type & IPV6_ADDR_MULTICAST)) {
+   net_dbg_ratelimited("ADDRCONF: unspecified / multicast 
address assigned as unicast address on %s",
+   idev->dev->name);
+   continue;
+   }
+
+   score->rule = -1;
+   bitmap_zero(score->scorebits, IPV6_SADDR_RULE_MAX);
+
+   for (i = 0; i < IPV6_SADDR_RULE_MAX; i++) {
+   int minihiscore, miniscore;
+
+   minihiscore = ipv6_get_saddr_eval(net, hiscore, dst, i);
+   miniscore = ipv6_get_saddr_eval(net, score, dst, i);
+
+   if (minihiscore > miniscore) {
+   if (i == IPV6_SADDR_RULE_SCOPE &&
+   score->scopedist > 0) {
+   /*
+* special case:
+* each remaining entry
+* has too small (not enough)
+* scope, because ifa entries
+* are sorted by their scope
+* values.
+*/
+   goto out;
+   }
+   break;
+   } else if (minihiscore < miniscore) {
+   if (hiscore->ifa)
+   in6_ifa_put(hiscore->ifa);
+
+   in6_ifa_hold(score->ifa);
+
+   swap(hiscore, score);
+
+   /* restore our iterator */
+   score->ifa = hiscore->ifa;
+
+   break;
+   }
+   }
+   }
+out:
+   read_unlock_bh(&idev->lock);
+}
+
 int ipv6_dev_get_saddr(struct net *net, const struct net_device *dst_dev,
   const struct in6_addr *daddr, unsigned int prefs,
   struct in6_addr *saddr)
 {
-   struct ipv6_saddr_score scores[2],
-   *score = &scores[0], *hiscore = &scores[1];
+   struct ipv6_saddr_score scores[2], *hiscore = &scores[1];
struct ipv6_saddr_dst dst;
+   struct inet6_dev *idev;
struct net_device *dev;
int dst_type;
+   bool use_oif_addr = false;
 
dst_type = __ipv6_addr_type(daddr);
dst.addr = daddr;
@@ -1380,97 +1459,35 @@ int ipv6_dev_get_saddr(struct net *net, const struct 
net_device *dst_dev,
 
rcu_read_lock();
 
-   for_each_netdev_rcu(net, dev) {
-   struct inet6_dev *idev;
-
-   /* Candidate Source Address (section 4)
-*  - multicast and link-local destination address,
-*the set of candidate source address MUST only
-*