Newly created DVR router as a result of new VM does not get ARP neighbors update, new VM has no connectivity

Bug #1438969 reported by Assaf Muller
8
This bug affects 1 person
Affects Status Importance Assigned to Milestone
neutron
Fix Released
Critical
Armando Migliaccio

Bug Description

Create a DVR router, connect it to subnet 'red'. Create a new VM connected to said subnet on a hypervisor that is currently not hosting any ports on the subnet. Before creation of the VM, the DVR qrouter namespace is does not exist. After the creation of the VM, it does.

However, observing neutron/db/l3_dvrscheduler_db._notify_l3_agent_new_port, we can see that L3 agents are first notified of new VMs going up for ARP purposes (l3plugin.dvr_vmarp_table_update), and then L3 agents are notified of the new VM (l3plugin.dvr_update_router_addvm, which also schedules the router on the new VM's node). This means that in the ARP notifier, the router is not scheduled yet on the new hypervisor, so the ARP entries for that subnet will not be sent to it. We can confirm this by seeing that the newly created router has no permanent entries in 'ip neigh'. Reversing the order of notifications (First notify L3 agents of the new VM, then send the ARP notification) is not a good fix because it's raceful... It only guarantees that the notification to configure the router is sent before the ARP RPC message, but not the actual configuration of the router. This results in the ARP RPC message failing to complete the 'ip neigh' command because the router doesn't exist yet.

Apparently the ARP entries in the qrouter namespace are not an optimization, they're mandatory. If a distributed router doesn't have an ARP entry for a remote VM, and it sends an ARP request, it won't be answered. I found out that the lack of static ARP entries in the distributed qrouter namespaces was an issue in the scenario above: The first VMs on compute nodes connected via distributed routers won't be able to ping each other.

Assaf Muller (amuller)
tags: added: l3-dvr-backlog
Assaf Muller (amuller)
description: updated
summary: DVR router newly created on a node as a result of new VM does not get
- ARP neighbors update
+ ARP neighbors update, new VM has no connectivity
summary: - DVR router newly created on a node as a result of new VM does not get
- ARP neighbors update, new VM has no connectivity
+ Newly created DVR router as a result of new VM does not get ARP
+ neighbors update, new VM has no connectivity
Changed in neutron:
assignee: nobody → Ila Palanisamy (ilavajuthy-palanisamy)
status: New → Confirmed
Revision history for this message
Armando Migliaccio (armando-migliaccio) wrote :

Um...wondering if this is a regression. Any chance you can back out to see how far back this used to work?

I wonder if 3f3874717c07e2b469ea6c6fd52bcb4da7b380c7 is the culprit.

Changed in neutron:
importance: Undecided → High
milestone: none → kilo-rc1
Revision history for this message
Armando Migliaccio (armando-migliaccio) wrote :

Um...I remember I had seen something similar. Is this a duplicate of bug #1411883? Please confirm.

Changed in neutron:
status: Confirmed → Incomplete
Revision history for this message
Armando Migliaccio (armando-migliaccio) wrote :

If my (wild) guess is correct, then the culprit is: https://review.openstack.org/#/c/113999/ and the attempted fix has somewhat stalled.

Revision history for this message
Swaminathan Vasudevan (swaminathan-vasudevan) wrote :

The problem here is not calling "_set_subnet_arp_info" from the "process_router" in L3-agent.
Originially in "Juno" the "_set_subnet_arp_info" was called in process_router. So even when the "arp_update" message has been dropped because of the non-existence of the "ri.router_info" for the given router_id it was able to update the router.

But now this "_set_subnet_arp_info" is only called when "internal_network" is added to the router.

That is the reason for this failure.

Also previously in "Juno" the "dvr_vmarp_table_update" was called from the ML2 plugin only for the "port-delete" and not the "port-create".

This bug got introduced by the l3 agent refactor and not by the https://review.openstack.org/#/c/113999/

This bug is not the same as "bug#1411883".

This is a valid bug.

Changed in neutron:
status: Incomplete → Confirmed
Revision history for this message
Assaf Muller (amuller) wrote :

Swami, looking at the code in the server it looks to me like the L3 agents won't receive the ARP messages at all because the routers are not scheduled yet. I'd love to know I'm wrong and the agents do receive the message but because of some agent bug the ip neigh command is not being executed. Can you confirm that the agents actually receive the ARP RPC messages when you spawn a new VM on a new compute?

Revision history for this message
OpenStack Infra (hudson-openstack) wrote : Fix proposed to neutron (master)

Fix proposed to branch: master
Review: https://review.openstack.org/170323

Changed in neutron:
assignee: Ila Palanisamy (ilavajuthy-palanisamy) → Swaminathan Vasudevan (swaminathan-vasudevan)
status: Confirmed → In Progress
Revision history for this message
Swaminathan Vasudevan (swaminathan-vasudevan) wrote :
Download full text (3.9 KiB)

Assaf yes the "RPC message is received by the agent" when you spawn an new VM on a Compute.

Most of the times I do see that it immediately returns with "ri.router_info" not found.

But once or twice I did see a "race condition" were the "arp_update" came in and the check for "ri.router_info" succeeded and then it errored when it was trying to add the arp entry into the given "qrouter-namespace".

2015-04-02 23:47:09.381 WARNING neutron.agent.l3.dvr [req-ae682b32-73cf-4ef5-b86d-4a7fe331bd9f None None] Inside Add arp entry
2015-04-02 23:47:09.381 DEBUG neutron.agent.linux.utils [req-ae682b32-73cf-4ef5-b86d-4a7fe331bd9f None None] Running command (rootwrap daemon): ['ip', 'netns', 'exec', 'qrouter-8070a83f-d16b-4990-ab33-732c9fc2d6ed', 'ip', '-4', 'neigh', 'replace', '10.1.0.3', 'lladdr', 'fa:16:3e:90:2d:10', 'nud', 'permanent', 'dev', 'qr-534334b1-c8'] from (pid=22638) execute_rootwrap_daemon /opt/stack/neutron/neutron/agent/linux/utils.py:98
2015-04-02 23:47:09.446 DEBUG neutron.agent.linux.utils [-]
Command: ['ip', '-o', 'netns', 'list']
Exit code: 0
Stdin:
Stdout:
Stderr: from (pid=22638) execute /opt/stack/neutron/neutron/agent/linux/utils.py:132
2015-04-02 23:47:09.446 DEBUG neutron.agent.linux.utils [-] Running command (rootwrap daemon): ['ip', 'netns', 'add', 'qrouter-8070a83f-d16b-4990-ab33-732c9fc2d6ed'] from (pid=22638) execute_rootwrap_daemon /opt/stack/neutron/neutron/agent/linux/utils.py:98
2015-04-02 23:47:09.447 ERROR neutron.agent.linux.utils [req-ae682b32-73cf-4ef5-b86d-4a7fe331bd9f None None]
Command: ['ip', 'netns', 'exec', u'qrouter-8070a83f-d16b-4990-ab33-732c9fc2d6ed', 'ip', '-4', 'neigh', 'replace', u'10.1.0.3', 'lladdr', u'fa:16:3e:90:2d:10', 'nud', 'permanent', 'dev', u'qr-534334b1-c8']
Exit code: 1
Stdin:
Stdout:
Stderr: Cannot open network namespace "qrouter-8070a83f-d16b-4990-ab33-732c9fc2d6ed": No such file or directory

2015-04-02 23:47:09.447 ERROR neutron.agent.l3.dvr_router [req-ae682b32-73cf-4ef5-b86d-4a7fe331bd9f None None] DVR: Failed updating arp entry
2015-04-02 23:47:09.447 TRACE neutron.agent.l3.dvr_router Traceback (most recent call last):
2015-04-02 23:47:09.447 TRACE neutron.agent.l3.dvr_router File "/opt/stack/neutron/neutron/agent/l3/dvr_router.py", line 195, in _update_arp_entry
2015-04-02 23:47:09.447 TRACE neutron.agent.l3.dvr_router device.neigh.add(ip, mac)
2015-04-02 23:47:09.447 TRACE neutron.agent.l3.dvr_router File "/opt/stack/neutron/neutron/agent/linux/ip_lib.py", line 538, in add
2015-04-02 23:47:09.447 TRACE neutron.agent.l3.dvr_router 'dev', self.name))
2015-04-02 23:47:09.447 TRACE neutron.agent.l3.dvr_router File "/opt/stack/neutron/neutron/agent/linux/ip_lib.py", line 222, in _as_root
2015-04-02 23:47:09.447 TRACE neutron.agent.l3.dvr_router use_root_namespace=use_root_namespace)
2015-04-02 23:47:09.447 TRACE neutron.agent.l3.dvr_router File "/opt/stack/neutron/neutron/agent/linux/ip_lib.py", line 69, in _as_root
2015-04-02 23:47:09.447 TRACE neutron.agent.l3.dvr_router log_fail_as_error=self.log_fail_as_error)
2015-04-02 23:47:09.447 TRACE neutron.agent.l3.dvr_router File "/opt/stack/neutron/neutron/agent/linux/ip_lib.py", line 78, in _execute
201...

Read more...

Revision history for this message
Carl Baldwin (carl-baldwin) wrote :

Swami said: 'But now this "_set_subnet_arp_info" is only called when "internal_network" is added to the router.

That is the reason for this failure. [...] This bug got introduced by the l3 agent refactor '

Here is where _set_subnet_info is called in Juno:

        for p in new_ports:
            self._set_subnet_info(p)
            self.internal_network_added(ri, p)
            ri.internal_ports.append(p)
            self._set_subnet_arp_info(ri, p)

So, it was only called when "internal_network" is added to the router. The refactoring moved things around but as far as I can tell it is called under the same conditions as it was before. So, we need more information about how _set_subnet_info is involved in this.

Revision history for this message
Carl Baldwin (carl-baldwin) wrote :

Swami said: 'previously in "Juno" the "dvr_vmarp_table_update" was called from the ML2 plugin only for the "port-delete" and not the "port-create".'

In Juno, dvr_vmarp_table_update was also called from neutron.plugins.ml2.rpc.RpcCallbacks.update_device_up called from treat_devices_added_or_updated in ovs_neutron_agent. Wouldn't this me called in the create port code path also?

It would help if we could pinpoint how far back this was broken. Git bisect could help here.

Revision history for this message
Carl Baldwin (carl-baldwin) wrote :

I think the comment thread here has ignored Armando's first comment (comment #1). Have you looked in to that commit as the potential culprit?

Revision history for this message
Swaminathan Vasudevan (swaminathan-vasudevan) wrote :

Hi Carl,
You right about the sequence "internal_network_added" and then calling the "_set_subnet_arp_info".
But now inside the "internal_network_added" it checks for external_gateway, snat and then calls the "_set_subnet_arp_info.
If anyone of this is not valid it quits.

So it does not hit the "_set_subnet_arp_info".

The new changes have altered the condition to call this function. That is what I was trying to say.

Revision history for this message
Swaminathan Vasudevan (swaminathan-vasudevan) wrote :

Carl yes I got that clarified that the dvr_vmarp_table_update is called for port_update. ( This is the same behavior for Juno and kilo).
Armando clarified it.

Revision history for this message
Carl Baldwin (carl-baldwin) wrote :

Looking deeper in to my comment #8. I do believe that https://review.openstack.org/#/c/154513 did change the behavior here. I just didn't see it at first. It moves _set_subnet_arp_info under internal_network_added in dvr_router.py but makes it conditional on a number of things where it was called unconditionally before. So, I think we found the culprit.

Changed in neutron:
assignee: Swaminathan Vasudevan (swaminathan-vasudevan) → Armando Migliaccio (armando-migliaccio)
Revision history for this message
Kyle Mestery (mestery) wrote :

Bumping to critical, as without this bug fix, the first VM booted by a tenant with a DVR router will not get an IP address from the DHCP agent.

Changed in neutron:
importance: High → Critical
Revision history for this message
OpenStack Infra (hudson-openstack) wrote : Fix merged to neutron (master)

Reviewed: https://review.openstack.org/170323
Committed: https://git.openstack.org/cgit/openstack/neutron/commit/?id=e585c822e38919451beeb95406c521b09b18e9fc
Submitter: Jenkins
Branch: master

commit e585c822e38919451beeb95406c521b09b18e9fc
Author: Swaminathan Vasudevan <email address hidden>
Date: Thu Apr 2 17:25:39 2015 -0700

    Fix dynamic arp populate error for dvr routers

    Recent refactor to the L3 Agent have introduced
    this problem. When we create a VM after we
    attach an interface to a router or when we add
    an interface with an existing VM to a router, in
    both cases the arp entries for the dvr serviced
    ports are not getting populated in the Router
    Namespace.

    Closes-Bug: #1438969

    Change-Id: I4a82e2435d176f3d9336d7f0dab9726c063840b9
    Co-authored-by: Armando Migliaccio <email address hidden>

Changed in neutron:
status: In Progress → Fix Committed
Thierry Carrez (ttx)
Changed in neutron:
status: Fix Committed → Fix Released
Revision history for this message
Assaf Muller (amuller) wrote :

To complete the discussion going on in comments 5 and 7, even if a router doesn't get an ARP RPC message (Because it wasn't yet scheduled, or because it was scheduled but not yet configured on the agent), when the router is configured on the agent it uses an RPC method to get all ports on its subnets and configures ARP entries for them. So I'm confident that feature should work as expected with this fix.

Thierry Carrez (ttx)
Changed in neutron:
milestone: kilo-rc1 → 2015.1.0
Revision history for this message
OpenStack Infra (hudson-openstack) wrote : Fix proposed to neutron (neutron-pecan)

Fix proposed to branch: neutron-pecan
Review: https://review.openstack.org/185072

To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.