Bug 1167969

Summary: it fails to assign a default IPv6 route if delayed after adding the IP address
Product: Red Hat Enterprise Linux 6 Reporter: João Avelino Bellomo Filho <jbellomo>
Component: kernelAssignee: Florian Westphal <fwestpha>
kernel sub component: IPv6 QA Contact: Hangbin Liu <haliu>
Status: CLOSED NEXTRELEASE Docs Contact:
Severity: low    
Priority: medium CC: jbellomo, kzhang, mleitner, network-qe, psimerda, rkhan, sibu, tgraf
Version: 6.6Keywords: Reopened
Target Milestone: rc   
Target Release: ---   
Hardware: Unspecified   
OS: Linux   
Whiteboard:
Fixed In Version: Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of:
: 1228700 (view as bug list) Environment:
Last Closed: 2015-07-08 14:58:22 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:
Bug Depends On:    
Bug Blocks: 1228700    

Description João Avelino Bellomo Filho 2014-11-25 18:31:29 UTC
Description of problem:

The ip command fails to assign a default IPv6 route from command line, but the same route configured through the configuration file (ifcfg-eth0) works well on starting (or restarting) the service network.

Version-Release number of selected component (if applicable):
iproute-2.6.32-32.el6_5 and previous

How reproducible:


Steps to Reproduce:
1. Enable the IPv6 on a NIC assign the IPv6 address 'fdde::1/128'

# cat /etc/sysconfig/network-scripts/ifcfg-eth0 
DEVICE="eth0"
BOOTPROTO="dhcp"
HWADDR="52:54:00:16:8F:13"
IPV6INIT="yes"
NM_CONTROLLED="yes"
ONBOOT="yes"
TYPE="Ethernet"
UUID="65882a64-4ca8-423b-b8af-64dd50b4550b"
IPV6ADDR=fdde::1/128

2. Restart the network

service network restart

3. Show the current IPv6 routes to eth0 NIC:

# ip -6 route show dev eth0
fdde::1  proto kernel  metric 256  mtu 1500 advmss 1440 hoplimit 4294967295
fe80::/64  proto kernel  metric 256  mtu 1500 advmss 1440 hoplimit 4294967295

4. Execute the command to configure the default route:

# /sbin/ip -6 route add default via fdde::1 metric 1

Actual results:

The command returns the message:

RTNETLINK answers: Invalid argument

And the error code '2'.

Executing the command to show routes again it shows the same list:

# ip -6 route show dev eth0
fdde::1  proto kernel  metric 256  mtu 1500 advmss 1440 hoplimit 4294967295
fe80::/64  proto kernel  metric 256  mtu 1500 advmss 1440 hoplimit 4294967295


Expected results:

The command should be executed without to show error message and the error code should be '0'.

Executing the command to show route should contains the default route on list:

# ip -6 route show dev eth0
fdde::1  proto kernel  metric 256  mtu 1500 advmss 1440 hoplimit 4294967295
fe80::/64  proto kernel  metric 256  mtu 1500 advmss 1440 hoplimit 4294967295
default via fdde::1  metric 1  mtu 1500 advmss 1440 hoplimit 4294967295


Additional info:

If the route is added to 'ifcfg-eth0' file:

# cat /etc/sysconfig/network-scripts/ifcfg-eth0
DEVICE="eth0"
BOOTPROTO="dhcp"
HWADDR="52:54:00:16:8F:13"
IPV6INIT="yes"
NM_CONTROLLED="yes"
ONBOOT="yes"
TYPE="Ethernet"
UUID="65882a64-4ca8-423b-b8af-64dd50b4550b"
IPV6ADDR=fdde::1/128
IPV6_DEFAULTGW=fdde::1

And the network restarted:

# service network restart
Shutting down interface eth0:                              [  OK  ]
Shutting down loopback interface:                          [  OK  ]
Bringing up loopback interface:                            [  OK  ]
Bringing up interface eth0:  
Determining IP information for eth0... done.
                                                           [  OK  ]

The default route is configured successfully:

 # ip -6 route show dev eth0
fdde::1  proto kernel  metric 256  mtu 1500 advmss 1440 hoplimit 4294967295
fe80::/64  proto kernel  metric 256  mtu 1500 advmss 1440 hoplimit 4294967295
default via fdde::1  metric 1  mtu 1500 advmss 1440 hoplimit 4294967295

I debugged the 'network-functions-ipv6' script and the route is assigned using the same commando that is used by command line:

/sbin/ip -6 route add default via fdde::1 metric 1

The error message came from the function 'rtnl_talk' on source file 'iproute2-2.6.31/lib/libnetlink.c':

295 int rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n, pid_t peer,
296           unsigned groups, struct nlmsghdr *answer,
297           rtnl_filter_t junk,
298           void *jarg)
299 {
...
337     while (1) {
338         iov.iov_len = sizeof(buf);
339         status = recvmsg(rtnl->fd, &msg, 0);
...
384             if (h->nlmsg_type == NLMSG_ERROR) {
385                 struct nlmsgerr *err = (struct nlmsgerr*)NLMSG_DATA(h);
386                 if (l < sizeof(struct nlmsgerr)) {
387                     fprintf(stderr, "ERROR truncated\n");
388                 } else {
389                     errno = -err->error;
390                     if (errno == 0) {
391                         if (answer)
392                             memcpy(answer, h, h->nlmsg_len);
393                         return 0;
394                     }
395                     perror("RTNETLINK answers");   <------------------
...

The function 'rtnl_talk' is called from 'iproute_modify':

 667 int iproute_modify(int cmd, unsigned flags, int argc, char **argv)
 668 {
...
 995     if (rtnl_talk(&rth, &req.n, 0, 0, NULL, NULL, NULL) < 0)
 996         exit(2);
 997 
 998     return 0;
 999 }

Comment 3 Pavel Šimerda (pavlix) 2015-03-03 16:51:20 UTC
(In reply to João Avelino Bellomo Filho from comment #0)
> IPV6ADDR=fdde::1/128
> # ip -6 route show dev eth0
> fdde::1  proto kernel  metric 256  mtu 1500 advmss 1440 hoplimit 4294967295
> fe80::/64  proto kernel  metric 256  mtu 1500 advmss 1440 hoplimit 4294967295

There is no default route in this case, and the IP address has no subnet as prefix length is 128.

> 4. Execute the command to configure the default route:
> 
> # /sbin/ip -6 route add default via fdde::1 metric 1

This command creates a default route but uses the machine's own address as the gateway. The correct way would be to use a subnet (e.g. fdde::1/64) and install a default route using another machine on the subnet (e.g. fdde::2/64).

Closing this bug report as the reported error is expected and matches current upstream behavior.

Comment 10 Florian Westphal 2015-05-21 08:41:34 UTC
Whats happening is that when the address is added (first command),
the kernel adds the prefix route and then starts duplicate-address-detection
(DAD) for the new address.

The route for the address is not added until after DAD completes.

While DAD is in progress, the "route add" sanity check that tests
if nexthop is local doesn't work yet since it only added the prefix route.
Once DAD is finished, the internal route lookup for the gateay address will
return a route via lo interface (which causes kernel to reject the gateway address), while its in progress the returned route will be via the interface
that the address was added on.

I submitted patch that makes the kernel always reject local nexthop regardless
of route table:
http://patchwork.ozlabs.org/patch/474672/

Comment 13 Florian Westphal 2015-07-08 14:58:22 UTC
I have no plans to backport this change to RHEL6 on the grounds that
it might break some existing script.

If you disagree please reopen this ticket, thanks!

RHEL7 clone bz is #1228700