Bug 969950

Summary: cant not add a range of virtual IPv6 addresses to interface
Product: Red Hat Enterprise Linux 6 Reporter: Geng Sheng Liu <gliu>
Component: iprouteAssignee: Petr Šabata <psabata>
Status: CLOSED NOTABUG QA Contact: BaseOS QE Security Team <qe-baseos-security>
Severity: medium Docs Contact:
Priority: unspecified    
Version: 6.4CC: dzhao, hafid.lin, psimerda
Target Milestone: rc   
Target Release: ---   
Hardware: x86_64   
OS: Linux   
Whiteboard:
Fixed In Version: Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2013-08-13 12:38:00 UTC Type: Bug
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:

Description Geng Sheng Liu 2013-06-03 07:13:40 UTC
Description of problem:

In IPv4 we can use the following command to add a ip subnet address to a interface like lo

#ip addr add 10.1.0.0/16 dev lo

But it failed in IPv6 with same command 

# ip -6 addr add 2001:4860:0:2001::68/64  dev lo 
# ping6 2001:4860:0:2001::68 
PING 2001:4860:0:2001::68(2001:4860:0:2001::68) 56 data bytes 
64 bytes from 2001:4860:0:2001::68: icmp_seq=0 ttl=64 time=0.036 ms 
 
--- 2001:4860:0:2001::68 ping statistics --- 
1 packets transmitted, 1 received, 0% packet loss, time 0ms 
rtt min/avg/max/mdev = 0.036/0.036/0.036/0.000 ms, pipe 2 
# ping6 2001:4860:0:2001::69 
connect: Network is unreachable 

Version-Release number of selected component (if applicable):


How reproducible:

always

Steps to Reproduce:
1. add ipv6 subnet address to a interface

#ip -6 addr add 2001:4860:0:2001::68/64  dev lo 





Actual results:

only 2001:4860:0:2001::68 get response from a ping command.

Expected results:

all address in 2001:4860:0:2001::68/64 should be available.

Additional info:

https://access.redhat.com/site/solutions/36876

http://post-office.corp.redhat.com/archives/tech-list/2010-February/msg00468.html

Comment 2 Petr Šabata 2013-06-03 13:02:45 UTC
(In reply to Geng Sheng Liu from comment #0)
> Additional info:
> 
> https://access.redhat.com/site/solutions/36876

This seems completely unrelated.

> http://post-office.corp.redhat.com/archives/tech-list/2010-February/msg00468.
> html

Basically I'd say the same as Neil did back in 2010, meaning IPv4 behaves incorrectly here.

Out of curiosity, could you elaborate on use cases of this "feature"?

Comment 4 Geng Sheng Liu 2013-06-04 02:09:00 UTC
Correction:

KBase related is as below

https://access.redhat.com/site/solutions/27284

Comment 5 Hafid Lin 2013-06-04 02:24:55 UTC
(In reply to Petr Šabata from comment #2)
> (In reply to Geng Sheng Liu from comment #0)
> > Additional info:
> > 
> > https://access.redhat.com/site/solutions/36876
> 
> This seems completely unrelated.
> 
> > http://post-office.corp.redhat.com/archives/tech-list/2010-February/msg00468.
> > html
> 
> Basically I'd say the same as Neil did back in 2010, meaning IPv4 behaves
> incorrectly here.
> 
> Out of curiosity, could you elaborate on use cases of this "feature"?
This feature is useful for stress testing. We used to simulated tens of thousands clients or severs on one blade server in IPv4 scenario, but in IPv6 scenario, we can't do same things again.

Comment 6 Hafid Lin 2013-06-13 07:56:52 UTC
Hi,

We found a workaround for this issue:

Steps:
1. add a IPv6 address on loopback interface
2. delete the unreachable route entry
3. add a local route entry

Example:
[root@bee12 ~]# ip -6 addr add fd96:38d8:6f3d:5e::/64 dev lo
[root@bee12 ~]# ip -6 route del unreachable fd96:38d8:6f3d:5e::/64
[root@bee12 ~]# ip -6 route add table local local fd96:38d8:6f3d:5e::/64 dev lo proto  kernel scope host

All IPv6 addresses under that network prefix can be accessed:
[root@bee12 ~]# ping6 fd96:38d8:6f3d:5e::1
PING fd96:38d8:6f3d:5e::1(fd96:38d8:6f3d:5e::1) 56 data bytes
64 bytes from fd96:38d8:6f3d:5e::1: icmp_seq=1 ttl=64 time=0.028 ms
^C
--- fd96:38d8:6f3d:5e::1 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 730ms
rtt min/avg/max/mdev = 0.028/0.028/0.028/0.000 ms
[root@bee12 ~]# ping6 fd96:38d8:6f3d:5e::2
PING fd96:38d8:6f3d:5e::2(fd96:38d8:6f3d:5e::2) 56 data bytes
64 bytes from fd96:38d8:6f3d:5e::2: icmp_seq=1 ttl=64 time=0.024 ms
^C
--- fd96:38d8:6f3d:5e::2 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 453ms
rtt min/avg/max/mdev = 0.024/0.024/0.024/0.000 ms
[root@bee12 ~]# ping6 fd96:38d8:6f3d:5e::fff1
PING fd96:38d8:6f3d:5e::fff1(fd96:38d8:6f3d:5e::fff1) 56 data bytes
64 bytes from fd96:38d8:6f3d:5e::fff1: icmp_seq=1 ttl=64 time=0.027 ms
^C
--- fd96:38d8:6f3d:5e::fff1 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 676ms
rtt min/avg/max/mdev = 0.027/0.027/0.027/0.000 ms

Comment 7 Pavel Šimerda (pavlix) 2013-06-21 13:19:23 UTC
I would like to note that this issue is specific to the loopback interface, as this bug report is used as a reference elsewhere.

It is related to the fact that the IPv6 standards do not define a loopback subnet but a single loopback address and therefore there is no need for it under normal circumstances.

(In reply to Hafid Lin from comment #6)
> Hi,
> 
> We found a workaround for this issue:
> 
> Steps:
> 1. add a IPv6 address on loopback interface
> 2. delete the unreachable route entry
> 3. add a local route entry

You might also want to try skipping steps #1 and #2 and only do #3 if the only thing you need to get it work is the local route entry itself.

> Example:
> [root@bee12 ~]# ip -6 addr add fd96:38d8:6f3d:5e::/64 dev lo
> [root@bee12 ~]# ip -6 route del unreachable fd96:38d8:6f3d:5e::/64
> [root@bee12 ~]# ip -6 route add table local local fd96:38d8:6f3d:5e::/64 dev
> lo proto  kernel scope host

As a sidenote, when I test this on 3.8.11 kernel (3.8.11-200.fc18.x86_64), and perform the three steps above, the ping won't work and reports 'Invalid argument' instead. Tried several times, used different IP ranges but might still be doing something wrong.

Comment 8 Geng Sheng Liu 2013-06-27 07:17:19 UTC
increase the kernel parameter below can solve the problem.

"net/core/dst.c"

    if (ops->gc && atomic_read(&ops->entries) > ops->gc_thresh) {
                if (ops->gc(ops))     <-----通过函数指针调用ip6_dst_gc
                        return NULL;

"net/ipv6/route.c"

static int ip6_dst_gc(struct dst_ops *ops)     <---------ipv6的gc函数
{
        unsigned long now = jiffies;
        struct net *net = container_of(ops, struct net, ipv6.ip6_dst_ops);
        int rt_min_interval = net->ipv6.sysctl.ip6_rt_gc_min_interval;
        int rt_max_size = net->ipv6.sysctl.ip6_rt_max_size;       <----------rt max size
        int rt_elasticity = net->ipv6.sysctl.ip6_rt_gc_elasticity;
        int rt_gc_timeout = net->ipv6.sysctl.ip6_rt_gc_timeout;
        unsigned long rt_last_gc = net->ipv6.ip6_rt_last_gc;

        if (time_after(rt_last_gc + rt_min_interval, now) &&
            atomic_read(&ops->entries) <= rt_max_size)
                goto out;

        net->ipv6.ip6_rt_gc_expire++;
        fib6_run_gc(net->ipv6.ip6_rt_gc_expire, net);
        net->ipv6.ip6_rt_last_gc = now;
        if (atomic_read(&ops->entries) < ops->gc_thresh)
                net->ipv6.ip6_rt_gc_expire = rt_gc_timeout>>1;
out:
        net->ipv6.ip6_rt_gc_expire -= net->ipv6.ip6_rt_gc_expire>>rt_elasticity;
        return (atomic_read(&ops->entries) > rt_max_size);        ------->here......
}

"net/ipv6/route.c" 
        net->ipv6.sysctl.flush_delay = 0;
        net->ipv6.sysctl.ip6_rt_max_size = 4096;    ----> default value of rt_max_size is 4096
        net->ipv6.sysctl.ip6_rt_gc_min_interval = HZ / 2;
        net->ipv6.sysctl.ip6_rt_gc_timeout = 60*HZ;


net.ipv6.route.max_size = 116184
(In reply to Pavel Šimerda from comment #7)
> I would like to note that this issue is specific to the loopback interface,
> as this bug report is used as a reference elsewhere.
> 
> It is related to the fact that the IPv6 standards do not define a loopback
> subnet but a single loopback address and therefore there is no need for it
> under normal circumstances.
> 
> (In reply to Hafid Lin from comment #6)
> > Hi,
> > 
> > We found a workaround for this issue:
> > 
> > Steps:
> > 1. add a IPv6 address on loopback interface
> > 2. delete the unreachable route entry
> > 3. add a local route entry
> 
> You might also want to try skipping steps #1 and #2 and only do #3 if the
> only thing you need to get it work is the local route entry itself.
> 
> > Example:
> > [root@bee12 ~]# ip -6 addr add fd96:38d8:6f3d:5e::/64 dev lo
> > [root@bee12 ~]# ip -6 route del unreachable fd96:38d8:6f3d:5e::/64
> > [root@bee12 ~]# ip -6 route add table local local fd96:38d8:6f3d:5e::/64 dev
> > lo proto  kernel scope host
> 
> As a sidenote, when I test this on 3.8.11 kernel (3.8.11-200.fc18.x86_64),
> and perform the three steps above, the ping won't work and reports 'Invalid
> argument' instead. Tried several times, used different IP ranges but might
> still be doing something wrong.

Comment 9 Petr Šabata 2013-08-13 12:38:00 UTC
As per Pavel's comment, this is not really an issue and the requested behavior can be achieved by adding the local route.

The proposed change in Comment #8 is for kernel and the customer ticket is already resolved.  I'm closing this as NOTABUG.