Skip to contentSkip to conversation

ping6 is sent out from wrong interface

DISCUSSION Naohiro Ooiwa 3 participants 7 messages Jun 25, 2008 – Jun 30, 2008

Subsystems (3)
lore
Share & tools
lore
#0 lore raw

Hi YOSHIFUJI-san

Thank you for your reply.

Quoted 3 lines

-I does not specify interface strictly but source address. Which means, if you just specify an address, interface is unspecified. You can give "-I eth1", too.

I'm not convinced yet.
I don't think it's correct that kernel or ping6 arbitrarily decides outgoing interface.

Is this really an expected behaviour?
Could you explain to me the reason of it, too?

I think the behavior should be similar to IPv4.

The following is my image. ipv6_dev_find() is an imaginary function, which finds the interface with a given source address.

How do you think?

net/ipv6/raw.c 2008-06-25 15:20:27.000000000 +0900 renamed from net/ipv6/raw.c.orig 2008-04-17 11:49:44.000000000 +0900 +7 -2
@@ -875,8 +875,13 @@ static int rawv6_sendmsg(struct kiocb *i
                final_p = &final;
        }
 
-       if (!fl.oif && ipv6_addr_is_multicast(&fl.fl6_dst))
-               fl.oif = np->mcast_oif;
+       if (!fl.oif && ipv6_addr_is_multicast(&fl.fl6_dst)) {
+               if (np->mcast_oif)
+                       fl.oif = np->mcast_oif;
+               else
+                       fl.oif = ipv6_dev_find(oldflp->fl6_src);
+       }
+
        security_sk_classify_flow(sk, &fl);
 
        err = ip6_dst_lookup(sk, &dst, &fl);
#1 lore raw

(usagi-users 04057) Re: ping6 is sent out from wrong interface

Hi Naohiro,

Quoted 8 lines

I'm not convinced yet.
I don't think it's correct that kernel or ping6 arbitrarily decides outgoing interface.

Is this really an expected behaviour?
Could you explain to me the reason of it, too?

I think the behavior should be similar to IPv4.

It's due to routing.

Your routing table shows this:
---

    # route -A inet6
    Kernel IPv6 routing table
    Destination            Next Hop Flags Metric Ref    Use Iface
    2001:2c0:418:1::/64    *        U     256    0        0 eth0
    2001:2c0:418:2::/64    *        U     256    0        0 eth1
    fe80::/64              *        U     256    0        0 eth0
    fe80::/64              *        U     256    0        0 eth1
    ::::::
    2001:2c0:418:1::1/128  *        U     0      8        1 lo
    2001:2c0:418:2::2/128  *        U     0      5        1 lo
    ::::::
    ff00::/8               *        U     256    0        0 eth0
    ff00::/8               *        U     256    0        0 eth1
    #
---

...with eth0 being preferred over eth1 for multicast packets.

You could add a dedicated route for ff02::/16 to make the kernel output the packet via eth1.

Bye,

Marcus
-----------------------------------------
IABG mbH
Sitz der Gesellschaft: Ottobrunn, Registergericht: Amtsgericht Muenchen, HRB 5499
Geschaeftsfuehrung: Prof. Dr.-Ing. Rudolf F. Schwarz
Vorsitzender des Aufsichtsrats: General a. D. Wolfgang Altenburg

#2 lore raw

Re: (usagi-users 04056) Re: ping6 is sent out from wrong interface

Hi Marcus

Thank you for your quick reply.

Quoted 1 line

It's due to routing.

For the reason of selecting 'eth0', I agree. But, I think the device is specified before looking up the routing table in this case.

Quoted 2 lines

...with eth0 being preferred over eth1 for multicast packets.
You could add a dedicated route for ff02::/16 to make the kernel output the packet via eth1.

This works when using only "eth1" for multicasts. When multiple I/Fs are connected to separate networks, this scheme requires changing the route every time a user need to send ping to different network.

I think kernel can solve this problem better.

Regards,
Naohiro Ooiwa

Fey Marcus さんは書きました:

Quoted 49 lines

Hi Naohiro,

Quoted 8 lines

I'm not convinced yet.
I don't think it's correct that kernel or ping6 arbitrarily decides outgoing interface.

Is this really an expected behaviour?
Could you explain to me the reason of it, too?

I think the behavior should be similar to IPv4.

It's due to routing.

Your routing table shows this:
---

    # route -A inet6
    Kernel IPv6 routing table
    Destination            Next Hop Flags Metric Ref    Use Iface
    2001:2c0:418:1::/64    *        U     256    0        0 eth0
    2001:2c0:418:2::/64    *        U     256    0        0 eth1
    fe80::/64              *        U     256    0        0 eth0
    fe80::/64              *        U     256    0        0 eth1
    ::::::
    2001:2c0:418:1::1/128  *        U     0      8        1 lo
    2001:2c0:418:2::2/128  *        U     0      5        1 lo
    ::::::
    ff00::/8               *        U     256    0        0 eth0
    ff00::/8               *        U     256    0        0 eth1
    #
---

...with eth0 being preferred over eth1 for multicast packets.

You could add a dedicated route for ff02::/16 to make the kernel output the packet via eth1.

Bye,

Marcus
-----------------------------------------
IABG mbH
Sitz der Gesellschaft: Ottobrunn, Registergericht: Amtsgericht Muenchen, HRB 5499
Geschaeftsfuehrung: Prof. Dr.-Ing. Rudolf F. Schwarz
Vorsitzender des Aufsichtsrats: General a. D. Wolfgang Altenburg

--
To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html

#3 lore raw

RE: (usagi-users 04056) Re: ping6 is sent out from wrong interface

Hi Naohiro,

Quoted 10 lines

Hi Marcus

Thank you for your quick reply.

Quoted 1 line

It's due to routing.

For the reason of selecting 'eth0', I agree.
But, I think the device is specified before looking up the routing table in this case.

Well, ping's man page reads:
---
-I interface address
Set source address to specified interface address. Argument may be numeric IP address or name of device. When pinging IPv6 link-local address this option is required.
---

So you only set the address, not the interface to be used for sending.

Quoted 10 lines
Quoted 3 lines

...with eth0 being preferred over eth1 for multicast packets. You could add a dedicated route for ff02::/16 to make the

kernel output the packet via eth1.

This works when using only "eth1" for multicasts. When multiple I/Fs are connected to separate networks, this scheme requires changing the route every time a user need to send ping to different network.

Ok, my proposition was a bit too general. It would probably be better to set up routes for the exact addresses. So in your case to ff02::1.

Of course, if you wish to send the same packet via several interfaces within a short time, this would still result in adding and deleting the routes over and over again.

Quoted 2 lines

I think kernel can solve this problem better.

I don't think this would be intended....

Bye,

Marcus
-----------------------------------------
IABG mbH
Sitz der Gesellschaft: Ottobrunn, Registergericht: Amtsgericht Muenchen, HRB 5499
Geschaeftsfuehrung: Prof. Dr.-Ing. Rudolf F. Schwarz
Vorsitzender des Aufsichtsrats: General a. D. Wolfgang Altenburg

#4 lore raw

Re: (usagi-users 04056) Re: ping6 is sent out from wrong interface

Hi Marcus

Thank you for your comment.

Quoted 16 lines
Quoted 7 lines

Thank you for your quick reply.

Quoted 1 line

It's due to routing.

For the reason of selecting 'eth0', I agree.
But, I think the device is specified before looking up the routing table in this case.

Well, ping's man page reads:
---
-I interface address
Set source address to specified interface address. Argument may be numeric IP address or name of device. When pinging IPv6 link-local address this option is required.
---

Quoted 1 line

So you only set the address, not the interface to be used for sending.

Then, the man page doesn't match with the implementation.

Quoted 11 lines
Quoted 10 lines
Quoted 3 lines

...with eth0 being preferred over eth1 for multicast packets. You could add a dedicated route for ff02::/16 to make the

kernel output the packet via eth1.

This works when using only "eth1" for multicasts. When multiple I/Fs are connected to separate networks, this scheme requires changing the route every time a user need to send ping to different network.

Quoted 9 lines

Ok, my proposition was a bit too general. It would probably be better to set up routes for the exact addresses. So in your case to ff02::1.

Of course, if you wish to send the same packet via several interfaces within a short time, this would still result in adding and deleting the routes over and over again.

Quoted 2 lines

I think kernel can solve this problem better.

I don't think this would be intended....

I was just confused by the difference of
source address things between IPv4 and IPv6.

Regards,
Naohiro Ooiwa

#5 lore raw

Re: (usagi-users 04056) Re: ping6 is sent out from wrong interface

In reply to Naohiro Ooiwa

In article <[email protected]> (at Wed, 25 Jun 2008 16:02:10 +0900), Naohiro Ooiwa <[email protected]> says:

Quoted 8 lines

Hi YOSHIFUJI-san

Thank you for your reply.

Quoted 3 lines

-I does not specify interface strictly but source address. Which means, if you just specify an address, interface is unspecified. You can give "-I eth1", too.

Quoted 5 lines

I'm not convinced yet.
I don't think it's correct that kernel or ping6 arbitrarily decides outgoing interface.

Is this really an expected behaviour?
Could you explain to me the reason of it, too?

I have to agree it is rather strange (or not natural), but, I do not agree with the solution.

In theory, outgoing interface must be selected by routing, if unspecified. So, I'd propose something like this (not tested, not for real patch).

net/ipv6/route.c +20 -9
index d1f3e19..81ddf9a 100644
@@ -239,17 +239,28 @@ static inline int rt6_need_strict(struct in6_addr *daddr)
 
 static inline struct rt6_info *rt6_device_match(struct net *net,
 						    struct rt6_info *rt,
+						    struct in6_addr *saddr,
 						    int oif,
 						    int strict)
 {
 	struct rt6_info *local = NULL;
 	struct rt6_info *sprt;
 
-	if (oif) {
-		for (sprt = rt; sprt; sprt = sprt->u.dst.rt6_next) {
-			struct net_device *dev = sprt->rt6i_dev;
+	if (!oif && ipv6_addr_any(saddr))
+		saddr = NULL;
+
+	for (sprt = rt; sprt; sprt = sprt->u.dst.rt6_next) {
+		struct net_device *dev = sprt->rt6i_dev;
+
+		if (oif) {
 			if (dev->ifindex == oif)
 				return sprt;
+		} else {
+			if (saddr && ipv6_chk_addr(net, saddr, dev, strict))
+				return sprt;
+		}
+
+		if (oif) {
 			if (dev->flags & IFF_LOOPBACK) {
 				if (sprt->rt6i_idev == NULL ||
 				    sprt->rt6i_idev->dev->ifindex != oif) {
@@ -261,13 +272,13 @@ static inline struct rt6_info *rt6_device_match(struct net *net,
 				}
 				local = sprt;
 			}
-		}
 
-		if (local)
-			return local;
+			if (local)
+				return local;
 
-		if (strict)
-			return net->ipv6.ip6_null_entry;
+			if (strict)
+				return net->ipv6.ip6_null_entry;
+		}
 	}
 	return rt;
 }
@@ -541,7 +552,7 @@ static struct rt6_info *ip6_pol_route_lookup(struct net *net,
 	fn = fib6_lookup(&table->tb6_root, &fl->fl6_dst, &fl->fl6_src);
 restart:
 	rt = fn->leaf;
-	rt = rt6_device_match(net, rt, fl->oif, flags);
+	rt = rt6_device_match(net, rt, &fl->fl6_src, fl->oif, flags);
 	BACKTRACK(net, &fl->fl6_src);
 out:
 	dst_use(&rt->u.dst, jiffies);
Signature · 2 lines
YOSHIFUJI Hideaki @ USAGI Project  <[email protected]>
GPG-FP  : 9022 65EB 1ECF 3AD1 0BDF  80D8 4807 F894 E062 0EEA
#6 lore raw

Re: (usagi-users 04056) Re: ping6 is sent out from wrong interface

Hi YOSHIFUJI-san

Thanks for your proposal.

Quoted 2 lines
Quoted 2 lines

In theory, outgoing interface must be selected by routing, if unspecified. So, I'd propose something like this (not tested, not for real patch).

This patch looks good enough to me.
I tested your patch and it works as I expected. I'm looking forward to seeing your final fix as well.

Thank you so much.
Naohiro Ooiwa